bash-내가 할 수있는 일 : find… -exec this && that?


23

find-exec 와 함께 호출되는 두 개의 쉘 명령을 논리적으로 결합하는 방법이 있습니까?

예를 들어 문자열 foo를 포함하는 모든 .csv 파일을 해당 항목과 함께 인쇄 하려면 다음과 같이하십시오.

find . -iname \*.csv -exec grep foo {} && echo {} \;

하지만 배쉬는 " '간부'에 인수 누락"로 불평


2
-exec순서대로 2 를 사용하거나 단일을 사용할 수 있습니다 -exec sh -c 'grep foo "$0" && printf %s\\n "$0"' {} \;.
jw013

이 반복적으로 나를 트립 : 난 항상 첫 번째 인수로 전달 기대 sh(이 경우 {}예정) $1$0같은 것입니다 sh. 그러나 실제로는 정확합니다. 첫 번째 인수는로 표시됩니다 $0. 첫 번째 인수를 호출 명령의 이름으로 지정하는 것은 규칙 일 뿐이며 이러한 경우에는 자동으로 적용되지 않습니다.
dubiousjim

어쩌면이 질문에 병합되어야한다 unix.stackexchange.com/q/18077/4801
dubiousjim

답변:


24

-exec쉘이 아닌 명령을 실행하고 명령 결과 (0 또는 0이 아닌 종료 상태)에 따라 true 또는 false로 평가되는 술어입니다 .

그래서:

find . -iname '*.csv' -exec grep foo {} \; -print

인쇄 할 경우 파일 경로를 grep발견 파일에 foo는. 대신 -print다른 -exec술어 또는 다른 술어를 사용할 수 있습니다

find . -iname '*.csv' -exec grep foo {} \; -exec echo {} \;

또한 참조 !-o부정과에 대한 연산자를 찾을 수 또는 .

또는 다음과 같이 쉘을 시작할 수 있습니다.

find . -iname '*.csv' -exec sh -c '
   grep foo "$1" && echo "$1"' sh {} \;

또는 모든 파일에 대해 쉘을 시작하지 않아도됩니다.

find . -iname '*.csv' -exec sh -c '
  for i do
    grep foo "$i" && echo "$i"
  done' sh {} +

10

문제 넌 직면 쉘은 먼저 명령 줄을 구문 분석, 그리고에 의해 분리 된 두 개의 간단한 명령 본다 &&운영자 : find . -iname \*.csv -exec grep foo {}echo {} \;. 인용하는 것은 &&( find . -iname \*.csv -exec grep foo {} '&&' echo {} \;) 그것을 무시하지만, 지금에 의해 실행 된 명령은 find같은 것입니다 grep인수와 foo, wibble.csv, &&, echowibble.csv. 연산자 find를 해석 할 쉘을 실행 하도록 지시해야합니다 &&.

find . -iname \*.csv -exec sh -c 'grep foo "$0" && echo "$0"' {} \;

이후의 첫 번째 인수 sh -c SOMECOMMAND$0아닙니다 $1.

명령 호출을로 그룹화하여 모든 파일에 대한 쉘 프로세스의 시작 시간을 절약 할 수 있습니다 -exec … +. 처리하기 쉽 $0도록 "$@"파일 이름 을 열거하는 더미 값을 전달 하십시오.

find . -iname \*.csv -exec sh -c 'for x in "$@"; do grep foo "$x" && echo "$x"; done' \ {} +

쉘 명령이 두 프로그램에 의해 분리 된 경우 &&, find그 자체로 작업을 수행 할 수 있습니다 쓰기 두 연속 -exec작업을하고있는 경우 두 번째에만 실행됩니다 상태 0 첫 번째 종료됩니다.

find . -iname \*.csv -exec grep foo {} \; -exec echo {} \;

(나는 가정 grep하고 echo같은 그림의 목적을 위해 단지이다 -exec echo로 대체 될 수 -print및 결과 출력이 특히 유용 어쨌든되지 않습니다.)


2
쉘에서 오류 메시지를 표시하는 데 사용되기 때문에 "$ 0"을 사용하지 않는 경향이 있습니다. 예를 들어, 혼란스러운 ./some-file: grep: command not found오류 메시지가 표시 될 수 있습니다 . -exec find sh -c '... "$1"' sh {} \;문제가 없을 것입니다. 두 번째 find 명령에 오타가 있습니다.
Stéphane Chazelas

3

이 특정한 경우에 나는 할 것이다 :

find . -iname \*.csv -exec grep -l foo \{\} \;

또는 ack 가있는 경우 :

ack -al -G '.*\.csv' foo

실제 질문에 대답하기 위해 다음과 같이 작동 할 수 있습니다.

find . -iname \*.csv -exec sh -c "grep foo {} && echo {}" \;


3
후자의 find 명령은 이식이 불가능할뿐만 아니라 파일 경로가 쉘 코드로 평가되기 때문에 매우 위험합니다.
Stéphane Chazelas

모든 시도하고 사용하여 그것을 피하기 위해 더 많은 이유를 ACK / 그렙 제대로 :)
데니스 Kaarsemaker

1
이와 관련하여 jw013의 대안 (질문에 대한 의견으로 제공됨)이 더 안전합니다. Gilles와 Stephane의 대답은 같은 기술을 사용한다는 것을 알았습니다.
dubiousjim
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.