특정 이름 패턴을 사용하여 수백만 개의 파일을 다른 디렉토리로 이동


10

Linux 컴퓨터에 다음과 같은 명명법을 가진 수백만 개의 파일이 있습니다.

1559704165_a1ac6f55fef555ee.jpg

처음 10 자리 숫자는 타임 스탬프이고 뒤에 오는 숫자 _는 특정 ID입니다. 특정 파일 이름 ID와 일치하는 모든 파일을 다른 폴더로 옮기고 싶습니다.

나는 파일이있는 디렉토리에서 이것을 시도했다.

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

그러나 다음을 나타내는 오류가 발생합니다.

bash 1559704165_a1ac6f55fef555ee.jpg: command not found

시도했을 때 mv ??????????_a1ac*.jpg 인수 목록에 너무 긴 오류가 발생했습니다. 적어도 15 개의 다른 파일 이름 패턴이 있습니다. 어떻게 이동합니까?


1
bash는 모든 것을 말합니다 : 파이프의 2 단계에서 첫 번째 줄이므로 해당 파일 이름 을 실행 하려고 시도합니다 (2 단계 파이프는 다음과 | ??????????_a1ac*.jpg같습니다 : : bash 는 파일 이름을 여러 파일 이름으로 확장 1559704165_a1ac6f55fef555ee.jpg합니다. , 그 두 번째 파이프 단계에서 실행하려고합니다 : 1559704165_a1ac6f55fef555ee.jpg next_matching_filename 3rd_matching_filename ... nth_matching_filename. 대신 파일 이름 을 필터링 하려고 시도한 것 같습니다 (아래 답변 참조)
Olivier Dulac

답변:


15

다음을 사용해야합니다.

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' \
-exec mv -t destination "{}" +

따라서 maxdepth 1현재 디렉토리에서 하위 디렉토리를 검색하지 않으려는 것을 의미합니다.

type f 파일 만 찾으라는 의미입니다.

name '??????????_a1ac*.jpg' 검색중인 파일과 일치하는 패턴입니다.

mv -t destination "{}" +일치하는 파일을 대상으로 이동하는 것을 의미합니다. 다음과 +같이 일치하는 새 파일을 이전 파일에 추가합니다.

mv -t dest a b c d

여기 abcd는 다른 파일입니다.


이 사람의 질문에 간결하게 답변 해 주셔서 감사합니다. 단순히 솔루션을 덤프하는 대신 방법 / 설명 / 이유를 설명 할 수 있습니다. 한 번에 한 사람에게 유용하지 않고 항상 모든 사람에게 유용 할 수 있습니다. 지난 40-50 년 동안 같은 질문이 무수히 여러 번 요청되었습니다. 문제는 잘 설명되지 않았다는 것입니다. 남자에게 물고기를 가르치십시오. 그 동안 : gnu.org/software/findutils/manual/html_node/find_html/… 위키 백과는 공식 문서보다 더 유용합니다 : en.wikipedia.org/wiki/Find_ ( 유닉스)
목소리

업데이트 된 답변을 참조하십시오.
Prvt_Yadav

참고 -t그래서 GNU의 확장 및 UNIX 파생 상품의 다른 유형에서 사용하지 못할 수 있습니다.
Kevin

"큰 따옴표는 단어 분리를 방지합니다." 라고 말할 때 나는 당신이 참조하고 있다고 가정합니다.이 "{}"경우 {}쉘에 의해 확장되지 않고 인용 할 필요가 없다는 것을 지적하고 싶습니다 . 쉘은 {}찾기 위해 전달 하고 find {}는이를 보고 경로 이름으로 바꿉니다. Find exec는 쉘 파서를 사용하지 않으며 자체적으로 단어 분할을 수행하지 않습니다. 그것이 아무런 해를 끼치 지 않는다고 인용하면 주어진 정당화가 약간 부정확하다는 것입니다.
jw013

@ jw013 감사합니다.
Prvt_Yadav

11

당신의 명령,

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

모든 파일 목록을 모든 파일로 파이프합니다!

find . -maxdepth 1 -type f -name `*_a1ac*.jpg` -print0 |\
xargs  -0 -r mv -t "/home/ubuntu/ntest"

트릭을 할 것입니다.


1
많은 감사 ... 솔루션도 효과가 ... 내가 어디로 잘못했는지 알려 주셔서 감사합니다
Apricot

8

당신은 매우 가깝습니다. -name옵션을 사용해야합니다 find. 그리고 패턴을 인용하는 것을 잊지 마십시오.

그래서

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' |xargs mv -t "/home/ubuntu/ntest"

많은 감사 ... 솔루션도 효과가있었습니다 .... 솔루션에 가까워 졌다는 사실을 알려 주셔서 감사합니다 ... 나 같은 초보자를위한 동기 부여
Apricot

1
당신은 추가해야 -print0찾기 (대신 기본 : -print)의 마지막 인자로하고, 추가 -0xargs를하는 첫 번째 옵션으로 (예 : xargs -0 mv -t "/home/ubuntu/ntest"). 이런 식으로 모든 종류의 이상한 파일 이름 (공백이 있거나 "줄 바꿈"등)을 처리 할 수 ​​있습니다. find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' -print0 |xargs -0 mv -t "/home/ubuntu/ntest" (하지만 GNU와 같은 find에서만 작동합니다)
Olivier Dulac

2

find솔루션 만큼 "좋은" 것이 아니라 또 다른 유효한 솔루션은 mv명령을보다 세분화하는 것입니다.

이것은 mv작업 당 더 적은 수의 파일 이동으로 4096 이동을 수행합니다.

FILEPAT=a1ac
for i in $(seq $((0x000)) $((0xfff))); 
do 
   H=$(printf '%x\n' $i)
   mv 1559704165_${FILEPAT}${H}*.jpg /home/ubuntu/ntest
done

이것은 find(어떤 이유로 든) 없는 사람들을위한 영리한 해킹입니다 .

-1

당신은 내가 당신과 함께하고있는 것 같아요 동일한 호스트 시스템에 파일을 이동하려는 경우 mv, rsync빠른 옵션이 될 수 :

rsync -av --inplace -W /source/??????????_a1ac*.jpg /home/ubuntu/ntest/

--inplace-W과정을 빠르게하도록 설정되어 있습니다.

이로 인해 다른 인수 목록이 너무 긴 오류가 발생 하면 목록을rsync

예를 들어 찾기로 목록을 만드십시오.

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txt

그리고 그것을 rsync

rsync -av --inplace -W --files-from=/tmp/my_image_list.txt /path/to/files /home/ubuntu/ntest/

여기에있는 출처는 귀하가 제공 한 목록을 출처를 기준으로 취급 /path/to/files하기 때문 rsync입니다.


요점은 파일이 동일한 파일 시스템에 있지 않은 경우 rsync보다 빠릅니다mv .


이것은 OP가 언급 한 것과 동일한 "인수 목록이 너무 깁니다"오류를
겪을 가능성이 있습니다

@Grump는이를 피하기 위해 OP가 파일 목록을 파일에 복사 find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txt한 다음이를 rsync에 전달할 수 --files-from=/tmp/my_image_list.txt있습니다. 요점 rsync은 더 빠릅니다. 파일이 동일한 파일 시스템에 상주하지 않는 한 OP는 표시하지 않았습니다.
Robert Riedl

@RobertRiedl : 답변을 편집하고이 정보를 추가해야합니다. 주석은 영구적이지 않을 수 있습니다.
NickD

@ NickD, 나는 대답을 업데이트했습니다.
Robert Riedl
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.