크기에 따라 파일을 재귀적으로 이동하고 구조를 유지하는 방법

크기에 따라 파일을 재귀적으로 이동하고 구조를 유지하는 방법

각 파일이 하위 폴더에 있는 하나의 디렉터리 트리에서 "300Mb"보다 큰 파일을 이동하고 싶습니다.

예: 다음과 같은 디렉터리 구조가 있습니다.

dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3

다음은 각 파일이 하위 폴더로 이동되는 디렉터리 트리의 "이동"인 예상 결과입니다.

dirB/            #  normal directory
dirB/file1       #  moved from dirA/file1
dirB/x/          #  normal directory
dirB/x/file2     #  moved from dirA/x/file2
dirB/y/          #  normal directory
dirB/y/file3     #  moved from dirA/y/file3

하지만 find /path/ -type f -size +300m그 다음엔? 불행하게도 일부 파일에는 키보드에서 찾을 수 있는 모든 종류의 문자가 포함되어 있습니다.

나 이거 보고왔어누가 얘기하는데 cpio그 프로그램은 모르겠어요...

추신: 속도를 높일 수 있다면 GNU Parallel을 설치하시겠습니까?

답변1

쉬운 방법은zsh. 당신이 사용할 수있는글로벌 한정자유형 및 크기와 같은 기준에 따라 파일을 일치시킵니다. 그만큼와일드카드 패턴 **/모든 수준의 하위 디렉터리와 일치합니다. 그만큼기록 수정자 h이는 t디렉토리와 파일 이름의 기본 부분을 추출하는 쉬운 방법입니다. 필요할 때 전화 mkdir -p하여 디렉토리를 생성하십시오.

cd dirA
for x in **/*(.Lm+300); do
  mkdir -p ../dirB/$x:h &&
    mv -- $x ../dirB/$x
done

휴대용 방법은 입니다 find. -exec모든 파일에 대해 셸 조각을 호출하는 데 사용됩니다 .

cd dirA
find . -type f -size +300000k -exec sh -c 'for x do
  mkdir -p "../dirB/${x%/*}"
  mv "$x" "../dirB/$x"
done' sh {} +

병렬화는 입출력에 거의 유용하지 않습니다. 병렬화를 사용하면 여러 CPU를 활용할 수 있지만 CPU가 I/O에서 병목 현상을 일으키는 경우는 거의 없습니다.

답변2

Perl이 rename확실한 선택입니다. ren, rename또는 다음과 같이 설치될 수 있습니다 pren.

find dirA -type f -size +300M | ren 's:^dirA/:dirB/:'

그러나 파일이 다른 마운트 지점으로 이동되면 작동하지 않으며 해당 디렉토리가 없으면 실패합니다.

GNU Parallel은 속도가 느려집니다.

cd dirA
find . -type f -size +300M | parallel mkdir -p ../dirB/{//}
find . -type f -size +300M | parallel mv {} ../dirB/{}

그러나 파일을 다른 파일 시스템으로 가져오기 위해 복사 후 제거 루틴을 수행해야 하는 경우에도 작동합니다.

답변3

간단히 말해서:

find dirA -type f -size +300m -printf "mv %p dirB/%P\n" | sh

그러나 시작하기 전에 dirB의 모든 하위 디렉터리가 존재해야 합니다. 이러한 이유로 다음 두 단계를 수행하는 것이 좋습니다.

cd dirA
find . -type f -size +300m -printf "mkdir -p ../dirB/%h\nmv %p ../dirB/%P\n" | sh

cpio 관련(실제로는 하위 디렉터리 문제를 해결합니다):

(cd dirA; find . -type f -size +300m) | cpio -p -md  dirB

(당신이 언급한 같은 스레드의 cp(1)에 관해서는 복사하기 때문에 당신에게 좋지 않습니다. 모두 파일 그리고 dirB 아래에 dirA라는 하위 디렉터리를 만듭니다. 깃발-티이 문제를 해결할 수 있습니다)

답변4

이 정도는 커버해야 합니다.

find /path -type f -size +300m | while read A ; do DEST=${A/dirA/dirB} ; echo mkdir -p $(dirname $DEST) 2>/dev/null; echo mv $A $DEST ; done

먼저 있는 그대로 실행하고 상태를 확인한 후 제안된 명령이 만족스러우면 요소 없이 다시 실행하세요 echo.

파일 구조 예에서는 다음 명령을 생성합니다.

mkdir -p ./dirB
mv ./dirA/file1 ./dirB/file1
mkdir -p ./dirB/x
mv ./dirA/x/file2 ./dirB/x/file2
mkdir -p ./dirB/y
mv ./dirA/y/file3 ./dirB/y/file3

관련 정보