find 명령 후 mv 명령을 통합하는 방법은 무엇입니까?


60

AAA다음 명령을 사용하여 경로에 이름이 포함 된 파일을 검색하고 있습니다 .

find path_A -name "*AAA*"

위의 명령으로 표시된 출력을 감안할 때 해당 파일을 다른 경로로 이동하고 싶습니다 path_B. 파일을 하나씩 이동하는 대신 find 명령 바로 다음에 해당 파일을 이동하여 명령을 최적화 할 수 있습니까?

답변:


86

GNU mv 사용 :

find path_A -name '*AAA*' -exec mv -t path_B {} +

그러면 find의 -exec옵션이 {}각 find 결과로 바뀌고 지정한 명령을 실행합니다. 에 설명 된대로 man find:

   -exec command ;
          Execute  command;  true  if 0 status is returned.  All following
          arguments to find are taken to be arguments to the command until
          an  argument  consisting of `;' is encountered.  

이 경우 가능한 적은 작업을 수행 할 수 있도록 +버전을 사용하고 있습니다.-execmv

   -exec command {} +
          This  variant  of the -exec action runs the specified command on
          the selected files, but the command line is built  by  appending
          each  selected file name at the end; the total number of invoca‐
          tions of the command will  be  much  less  than  the  number  of
          matched  files.   The command line is built in much the same way
          that xargs builds its command lines.  Only one instance of  `{}'
          is  allowed  within the command.  The command is executed in the
          starting directory.

"\;"를 잊지 마십시오 exec의 끝에서!
Charles Roth

@ 찰스 로스 : 그것은 일을 다우 +는 것입니다, 당신은 위의 견적을 읽을 수 있습니다man find
cuonglm

감사합니다! 사용하려고했지만 -exec mv {} path_b +권한 오류로 실패했습니다. TBH, 나는 여전히 이유를 이해하지 못하지만 -exec mv -t path_b {} +대접을합니다!
Jeremy Davis

6
사용하는 경우 @JeremyDavis -exec ... {} +는이 {}전과 마지막 일 수있다 +. 그가 사용하는 이유입니다 mv -t destdir {} +하지 mv {} destdir +. 하나의 콜드가 -exec mv {} destdir ';'대신 사용 되었지만 mv각 파일마다 한 번씩 실행 되었습니다.
Kusalananda

23

아래처럼 할 수도 있습니다.

find path_A -name "*AAA*" -print0 | xargs -0 -I {} mv {} path_B

어디,

  1. -0공백이나 문자 (줄 바꿈 포함)가 있으면 많은 명령이 작동하지 않습니다. 이 옵션은 공백이있는 파일 이름을 처리합니다.
  2. -I초기 인수에서 replace-str 발생을 표준 입력에서 읽은 이름으로 바꾸십시오. 또한 인용되지 않은 공백은 입력 항목을 종료하지 않습니다. 대신 구분 기호는 개행 문자입니다.

테스팅

I는 두 개의 디렉토리를 생성 sourcedir하고 destdir. 지금, 나는 내 파일의 무리 생성 sourcedir등을 file1.bak, file2.bak그리고file3 with spaces.bak

이제 명령을 다음과 같이 실행했습니다.

find . -name "*.bak" -print0 | xargs -0 -I {} mv {} /destdir/

이제, 내부 destdir내가 할 때 ls, 나는 파일에서 이동 한 것을 볼 수 있습니다 sourcedirdestdir.

참고 문헌

http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/


22

이 질문을 통해 OS X 사용자의 이익을 얻으려면 OS X의 구문이 약간 다릅니다. 다음의 하위 디렉토리에서 재귀 적으로 검색하고 싶지 않다고 가정합니다 path_A.

find path_A -maxdepth 1 -name "*AAA*" -exec mv {} path_B \;

다음에서 모든 파일을 재귀 적으로 검색하려면 다음을 수행하십시오 path_A.

find path_A -name "*AAA*" -exec mv {} path_B \;

이것은 OS X 고유의 구문이 아니며, find내가 사용한 것과 동일합니다 . 좋은 점 : -maxdepth(특히 path_B가 서브 디렉토리 인 경우- mv파일을 이미 이동 시키지 마십시오 !) 및 \; (따라서 {}는 마지막 매개 변수 일 필요는 없으며 일반 mv구문을 사용할 수 있습니다)
drevicko

6

-exec이 작업을 수행하는 가장 좋은 방법입니다. 어떤 이유로 든 이것이 옵션이 아닌 경우 루프에서 결과를 읽을 수도 있습니다.

find path_A -name "*AAA*" -print0 | 
    while IFS= read -r -d $'\0' file; do mv "$file" path_B; done

안전한 방법입니다. 공백, 줄 바꿈 또는 기타 이상한 문자가 포함 된 파일 이름을 처리 할 수 ​​있습니다. 더 간단한 방법이지만 파일 이름이 간단한 영숫자로만 구성되지 않으면 실패 하는 방법 은 다음과 같습니다.

mv $(find path_A -name "*AAA*") path_B

그러나 while 루프를 사용하십시오.


여전히 경우 실패 할 수있는 간단한 방법 your file names consist only of simple alphanumeric characters예를 들어, 경우에 도달ARG_MAX


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.