파일 유형별로 큰 디렉터리 트리 분할

파일 유형별로 큰 디렉터리 트리 분할

내 Ubuntu 10.10 데스크탑에는 많은 원시 데이터 파일, 처리된 데이터 파일 및 처리된 데이터에서 생성된 다양한 스크립트, 테이블, 그래프 등이 포함된 대용량 데이터 디렉터리(20-30Gb)가 있습니다. 데이터 카탈로그는 수년에 걸쳐 축적되었으며 구조가 잘못되어 있습니다. "언젠가는" 정리하겠지만 항상 더 중요한 할 일이 있습니다.

지금은 온라인 백업 서비스로 전환 중인데, 백업에 소요되는 시간과 필요한 온라인 저장 공간을 줄이기 위해 공간을 많이 차지하지만 쉽게 대체할 수 있는 원본 데이터를 분할하고 싶습니다. 디렉토리 구조에서 일반 위치를 유지하면서 다른 곳에 보관된 항목입니다. 즉, 저는 다음과 같은 곳에서 시작하고 싶습니다.

/data/A/raw1.data
/data/A/raw2.data
/data/A/raw3.data
/data/A/processed.txt
/data/A/figure.eps
/data/A/plot.gnu
/data/B/raw4.data
/data/B/processed.txt
... etc.

도착하다

/data/A/processed.txt
/data/A/figure.eps
/data/A/plot.gnu
/data/B/processed.txt
... etc.

그리고

/raw_data/A/raw1.data
/raw_data/A/raw2.data
/raw_data/A/raw3.data
/raw_data/B/raw4.data
... etc.

따라서 원시 데이터 파일은 /data에서 /raw_data로 교체되지만 디렉터리 구조에서의 위치는 유지되고 처리된 데이터 및 관련 파일은 동일한 위치에 유지됩니다. 전체 파일 구조는 이보다 훨씬 더 복잡하고 체계적이지 않지만 모든 원시 데이터를 파일 유형(주로 .fits 및 .sdf)으로 식별할 수 있다는 장점이 있습니다.

올바른 명령 조합 및/또는 몇 줄의 bash 스크립트를 사용하면 이것이 사소한 일이라고 확신하지만 명령줄 지식은 기본으로 제한되어 있으므로 엉망이 되는 위험을 감수하기보다는 물어보고 싶습니다. :)

그런데 원본 데이터에서 중복 항목을 쉽게 찾을 수 있는 방법이 있습니까? 동일한 파일 이름 + 크기를 가지게 되며 반드시 타임스탬프는 아니더라도 아카이브에서 데이터를 다운로드할 때 재설정됩니다. 맞춤 헤더의 타임스탬프에 대해 dfits 및 grep을 통해 각 중복 후보를 파이프해야 합니다.

답변1

rsync한 가지 방법은 다음과 같이 특별히 제작된 포함/제외 규칙과 동기화 후 소스 파일을 삭제하는 옵션을 사용하는 것입니다 .

rsync -av --include "*/" --include='*.fits' --include='*.sdf' \
    --exclude='*' --remove-source-files /data/ /raw_data/

다른 작업을 포함하여 루프에서 단계별로 이동하려면 다음과 같은 스크립트가 필요합니다.

DIR1="/data"
DIR2="/raw_data"

find "$DIR1" -type f \( -iname '*.fits' -or -iname '*.sdf' \) -print0 |
    while read -d $'\0' file; do
        mkdir -p "$DIR2/$(basename "$file")"
        mv "$file" "$DIR2/$(basename "$file")"
    done

답변2

충분히 유연한 규칙을 사용하여 대상 디렉터리 이름( zcp, rsync, pax, ...) 을 구성할 수 있는 파일 복사 도구가 많이 있습니다. 불행하게도 그 중 필요에 따라 대상 디렉토리를 이동(복사 아님)하고 생성하는 것을 허용하는 경우는 거의 없습니다. 따라서 두 가지 단계로 수행되는 몇 가지 방법을 보여 드리겠습니다. 먼저 가능한 모든 필수 대상 디렉터리를 생성한 다음 이동을 수행합니다.

펄 이름 바꾸기

rename필요한 Perl 부분을 작성하면 Debian 및 Ubuntu와 함께 제공되는 Perl 프로그램이 필요한 경우 대상 디렉터리를 생성할 수 있습니다.

shopt -s globstar       # make **/ traverse directories recursively (requires bash 4)
rename 'BEGIN {use File::Path}
        s!^/data!/raw_data!;
        m!(.*)/!; mkpath($1)' /data/**/*.raw

zsh에서는 이 shopt -s globstar줄이 생략되었습니다. **기본값은 재귀 순회를 의미합니다. bash 및 zsh 이외의 쉘에서는 재귀 순회를 사용해야 합니다 find(아래 예 참조). 단일 레벨 디렉토리만 있다면 이 모든 것에 대해 걱정할 필요가 없습니다.

대상 디렉터리 생성

zsh에서(설명:/ 글로벌 예선이는 디렉토리만 일치하고 eglob 한정자는 나중에 각 이름에 지정된 변환을 적용함을 의미합니다.

mkdir /data/**/*(/e\''REPLY=${REPLY/data/raw_data}'\')

다른 쉘의 경우:

find /data -type d \
     -exec sh -c 'for d; do mkdir "/raw_data${d#/data}"; done' _ {} +

한 수준의 하위 디렉터리만 있는 경우 훨씬 간단합니다.

for d in /data/*/; do mkdir "/raw_data${d#/data}"; done

파일 이동(zsh)

autoload zmv
zmv -Q '/data/(**/)(*.raw)(.)' '/raw_data/$1$2'

파일 이동(휴대용)

find /data -name '*.raw' \
     -exec sh -c 'for x; do mv "$x" "/raw_data${x#/data}"; done' _ {} +

관련 정보