find를 다른 명령과 결합: 언제 -exec를 사용하고 언제 파이프를 사용합니까?

find를 다른 명령과 결합: 언제 -exec를 사용하고 언제 파이프를 사용합니까?

파일과 디렉토리를 찾기 위해 find 명령을 단독으로 사용하는 방법을 배웠습니다. 그러나 파일/폴더로 작업을 수행할 때 혼란스럽습니다.

다음 명령이 주어졌습니다.

find . -type f -iname "*.cr2" 

위에서 찾은 파일을 새 디렉터리에 복사하려면 당연히 copy( cp) 및 Pipe를 사용한다고 생각합니다 |.

find . -type f -iname "*.cr2" | cp \destination_directory

그리고 나에게 이것은 전체 드라이브에 있는 모든 사진을 가져오고 하위 폴더 수준에 중첩되어 정리를 시작할 준비가 된 단일 폴더에 저장됩니다.

그러나 사람들은 계속해서 매개변수를 사용하라고 말합니다 . 그래서 제 질문은 아래와 같이 언제 파이프를 사용해야 하는지 , 언제 명령을 사용해야 하는지 -exec어떻게 알 수 있느냐는 것입니다 .|-exec

 find . -name "*.pdf" -type f -exec cp {} ./pdfsfolder \;

편집하다

아래 제안된 솔루션은 파일 이름이 고유한 파일만 복사합니다. cp는 file.txt를 복사하지 않고 file.txt로 바꾸지 않을 것이라고 말합니다. 많은 파일을 복사했는데 같은 이름의 파일이 있을지 모르는 경우, 복사한 후 파일 이름이 있으면 이름을 바꾸라고 어떻게 말합니까?

제안된 솔루션

find . -type f -iname "*.txt" -print0 | xargs -0 cp -t /home/josh/Documents/copy/

/home/josh/documents/copy는 물건을 옮기고 싶은 디렉토리입니다.

답변1

귀하의 가정에는 오류가 있지만 먼저 몇 가지 배경 지식이 있습니다.

다음의 두 가지 용도를 식별해야 합니다 -exec.

  • 은 ( \;는) {} 발견된 단일 항목으로 대체됩니다.
  • 은 많은 +항목 {}으로 대체됩니다(명령줄에 담을 수 있는 만큼).

따라서 사용 예에서는 에서 찾은 항목만큼 -exec많은 명령을 호출합니다 .cpfind

사용은 find ... -exec cmd {} ... +find의 출력을 여러 입력 이름을 처리하는 명령으로 파이프하는 것과 효율성이 비슷합니다.

-exec공백이 포함된 파일 이름/경로를 훌륭하게 처리하지만 find에서 다른 프로그램으로 출력을 파이프할 때 문제가 발생할 수 있다는 점도 고려해야 합니다 . 따라서 stdin에서 파일 이름 목록을 기대하는 일부 프로그램에는 해당 파일 이름을 NUL로 구분하는 옵션이 제공될 수 있습니다(종종 -0또는 --null). 그리고 find다음을 지정하여 그런 식으로 다음 프로그램에 제공할 수 있는 옵션이 있습니다.-print0


이제 귀하의 예를 살펴 보겠습니다.

find . -type f -iname "*.cr2" | cp destination_directory

cp는 표준 입력에서 읽지 않으므로 찾은 파일을 복사하지 않습니다. 다음을 사용해야 합니다.

find . -type f -iname "*.cr2" | xargs cp -t destination_directory

또는 공백이 있는 경로를 처리하려면 다음을 수행하십시오.

find . -type f -iname "*.cr2" -print0 | xargs -0 cp -t destination_directory

거의 동일한 효율성으로 다음을 수행할 수 있습니다.

find . -type f -iname "*.cr2" -exec cp -t destination_directory {} +

(G-Man이 지적했듯이 는 {}끝에 있어야 하며 +) 위의 모든 내용은 다음과 같습니다.~ 아니다이를 위해 대상 디렉토리 아래에 계층 구조를 구축하고 소스 디렉토리가 단순하더라도 오랜 습관으로 대신 다음을 사용합니다 cpio.

find . -type f -iname "*.cr2" -print0 | cpio -pdmv0 destination_directory

그 과정에서 무엇을 하고 있는지 잘 나열되어 있습니다.


관련 부품 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.  The string
       `{}'  is  replaced  by  the  current  file name being processed
       everywhere it occurs in the arguments to the command, not  just
       in  arguments  where  it is alone, as in some versions of find.
       Both of these constructions might need to be  escaped  (with  a
       `\')  or  quoted  to  protect them from expansion by the shell.
       See the EXAMPLES section for examples of the use of  the  -exec
       option.   The  specified  command  is run once for each matched
       file.  The command  is  executed  in  the  starting  directory.
       There  are unavoidable security problems surrounding use of the
       -exec action; you should use the -execdir option instead.

-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.

관련 정보