각 찾기 결과에 대해 특정 명령을 어떻게 실행할 수 있습니까?


49

명령을 사용하여 찾은 각 파일에 대해 특정 명령을 어떻게 실행 find합니까? 질문의 목적으로에 의해 찾은 각 파일을 삭제하고 싶다고 말할 수 있습니다 find.

답변:


60

편집 : 다음 답변은 일반적인 사용 사례를 설명하지만 파일과 디렉토리를 삭제하는 것은 특별한 경우입니다. -execdir rm {} \;구문 을 사용하는 대신 다음과 같이을 사용하십시오 -delete.

find -iname '*.txt' -delete

이것은 오류가 발생하지 않도록 삭제해야 할 순서 파일 및 디렉토리를 포함시키는 것에 대해 생각할 수없는 많은 경우를 처리합니다. 다른 사용 사례의 경우 ...

찾기 결과의 실행 명령을 처리하는 가장 좋은 방법은 일반적으로 명령에 다양한 -exec옵션을 사용하는 것 find입니다. 특히 -execdir, 발견 된 파일의 디렉토리 내에서 실행되며 일반적으로 다른 옵션보다 멍청한 실수를 막는다는 의미에서 더 안전하기 때문에 가능할 때마다 사용해야 합니다.

-exec옵션은 사용자가 실행하고 싶은 명령 준수 {}발견에 의해 발견 된 파일이 포함되어야하며,에 의해 해지 된 자리를 나타내는 \;각 파일에 대해 명령을 한 번 실행하거나 +대체하기 위해 {}모든 경기의 인수 목록으로 . 세미콜론 종결자는 이스케이프 처리되어 쉘에서 새 명령으로 이어지는 분리 자로 이해되지 않습니다.

모든 텍스트 파일을 찾고 있다고 가정 해 보겠습니다.

find -iname '*.txt' -execdir rm {} \;

찾기 매뉴얼 ( 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 sec-
          tion for examples of the use of the -exec option.  The specified
          command is run once for each matched file.  The command is  exe-
          cuted  in  the starting directory.   There are unavoidable secu-
          rity 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.


   -execdir command ;

   -execdir command {} +
          Like -exec, but the specified command is run from the  subdirec-
          tory  containing  the  matched  file,  which is not normally the
          directory in which you started find.  This a  much  more  secure
          method  for invoking commands, as it avoids race conditions dur-
          ing resolution of the paths to the matched files.  As  with  the
          -exec action, the ‘+’ form of -execdir will build a command line
          to process more than one matched file, but any given  invocation
          of command will only list files that exist in the same subdirec-
          tory.  If you use this option, you must ensure that  your  $PATH
          environment  variable  does  not  reference  ‘.’;  otherwise, an
          attacker can run any commands they like by leaving an  appropri-
          ately-named  file in a directory in which you will run -execdir.
          The same applies to having entries in $PATH which are  empty  or
          which are not absolute directory names.

Busybox가 제공하는 "find"명령은 -execdir 옵션을 지원하지 않으므로 아래 언급 된 pipe / xargs 방법 중 하나를 사용해야합니다.
MikeW

9

대안은 출력을 파이프하고 후속 명령으로 구문 분석하는 것입니다. 이렇게하는 유일한 안전한 방법 은 결과 구분 기호로 null 문자를 사용 하도록하는 -print0옵션 find을 사용하는 것입니다. 수신 명령에는 널로 구분 된 입력을 인식 할 수 있어야합니다. 예:

find /home/phunehehe -iregex '.*\.png$' -print0 | xargs -0 file

-0옵션은 xargs입력을 널로 구분하여 처리하도록 지시 합니다.


대신 -exec파일을 끝내면 더 많은 파일을 사용할 수 있습니다 . caleb의 답변을 참조하십시오. +;
Kevin

@ 케빈 당신이 맞아, 나는 대답을 업데이트했다.
phunehehe

3

Find에 내장 된 삭제 명령이 있으면됩니다.

find . -name "*.txt" -delete

찾은 .txt 파일은 위 명령을 사용하여 삭제됩니다.


2

나는 이것에 대한 답을 찾고 있었고이 실을 우연히 발견했다. 그 대답은 내게 어떻게 그것을 달성 할 수 있는지에 대한 아이디어를 주었다. mediainfo모든 JPEG 파일 을 찾고 싶다고 가정 하십시오.

이것은 일치하는 모든 파일 mediainfo "의 시작과 "끝에 추가 합니다 (가능한 한 특수 문자를 이스케이프하려면). 스크립트에 넣고 스크립트를 실행하십시오.

find . -name *.jpg | sed -e 's/^/mediainfo "/g;' | sed -e 's/$/"/g;' > foo.sh && sh foo.sh

문제가 생길 우려가있는 경우 출력을 파일로 리디렉션하는 것을 건너 뛰고 스크립트를 실행하기 전에 터미널에서 결과를 확인할 수 있습니다.


1

xargs명령을 사용하여이를 수행 할 수 있습니다 . xargs기본 입력의 각 명령마다 기본적으로 명령을 한 번 실행합니다. .jpg예를 들어 디렉토리의 모든 파일 을 삭제해야하는 경우 명령 행에서 빠른 방법은 다음과 같습니다.

$ find ./ -name "*.jpg" | xargs rm 

탭 버튼 위에있는 역 따옴표를 사용하여이를 수행 할 수도 있습니다 (이것은 작은 따옴표 문자가 아닌 역 따옴표 문자입니다).

$ rm `find ./ -name "*.jpg"`

xargs쉘이 입력을 처리 하는 방식 과 방법으로 인해 xargs 메소드는 관련된 파일 이름 및 디렉토리 이름에 공백이나 공백이없는 경우에만 작동합니다 \"'. backquote 메소드는 관련된 파일 이름 및 디렉토리 이름에 공백 또는를 포함하지 않는 경우에만 작동합니다 \[?*.


3
이 두 가지 방법 모두 잠재적으로 매우 위험합니다. 파일 이름에 이스케이프 처리되지 않은 문자에는 여러 가지 잠재적 인 문제가있어 이러한 메소드가 중단 될 수 있습니다.
Caleb

1
요점을 알지만 이러한 명령은 찾기 이외의 다른 도구와 함께 사용할 수도 있으므로 여기서 언급 할 가치가 있다고 생각합니다.
IG83

언급 할 가치가 있지만 사용 하지 않을 때는 지정하는 것이 중요합니다. 여기서 OP의 질문은의 출력 처리를 구체적으로 요청했으며 find, -exec일반적으로 더 나은 솔루션입니다. 이것을 대체물로 지정하려면 최소한 find -print0 | xargs -0안전한 파일 이름 나누기 처리 방법을 설명 하고 백틱에주의해야 할 시점을 자세히 설명하십시오.
Caleb

1
그런데 사이트에 오신 것을 환영합니다. 이것이 첫 번째 답변이라는 것을 알았습니다. 온통 뛰어 내려 죄송합니다. 사람들에게 문제를 미리 가르치는 것이 중요하기 때문에 나중에 이해하기 어려운 실수를 저 지르지 않지만 왜 이것이 그렇게 큰 문제인지 이해하지 못한 시절을 기억합니다. 개인적으로 정정을 취하지 마십시오.
Caleb

3
환영합니다! 물론 딱딱한 감정은 없습니다. 당신은 확실히 -exec가 이것을 처리하는 적절한 방법이라는 점에서 옳습니다. 나는이 플랫폼이 얼마나 위대한 지보기 시작했습니다. 여러분은 주석에서도 새로운 것을 배우고 있습니다 :)
IG83
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.