찾기 : -exec에 대한 인수 누락


18

다음 명령을 실행하려고합니다.

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' +

이것은 오류를 반환합니다 :

find: missing argument to -exec

이 명령의 맨 페이지와 일치하는 것처럼 보이는이 명령의 문제점을 볼 수 없습니다.

-exec 명령 {} +

이 -exec 옵션 변형은 선택된 파일에서 지정된 명령을 실행하지만 명령 행은 선택한 각 파일 이름을 끝에 추가하여 빌드됩니다. 명령의 총 호출 수는 일치하는 파일 수보다 훨씬 적습니다. 명령 행은 xargs가 명령 행을 빌드하는 것과 거의 같은 방식으로 빌드됩니다. 명령 내에서 하나의 '{}'인스턴스 만 허용됩니다. 명령은 시작 디렉토리에서 실행됩니다.

나는 또한 시도했다 :

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' '{}' +
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar '{}' +
find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar '{}' +
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+

+끝에 탈출을 시도 했습니까 ? find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
jayhendren

3
구버전의 GNU를 사용하고있을 수 있습니다 find. 이 -exec cmd {} +변종은 POSIX이며 80 년대부터 사용 가능 했지만 GNU는 최근에 상대적으로 최근에 추가 한 것만 발견했습니다 (2005). 무엇을 find --version말합니까?
Stéphane Chazelas

2
@Koveras, 그럴 것입니다. -exec {} +구식 GNU 발견에서는 (비 POSIX) -print0 | xargs -r0를 사용하여 비슷한 것을 얻을 수 있습니다. 4.11994 년부터입니다
스테판 Chazelas가

1
JRFerguson은 -name패턴 인수가 인용되어야한다고 ( 삭제 된 답변으로) 지적했습니다 -name "*.c" -o -name "*.h". -exec오류 와 관련이 없지만 사실 입니다. Gilles만이 언급하지만 다른 모든 답변은 와일드 카드를 따옴표로 묶는 것을 알 수 있습니다. … (계속)
G-Man, 'Reinstate Monica'라고

1
(계속)… jlliagre의 답변은 -name "*.[ch]"설명없이 이름 표현을 무너 뜨립니다 . 이것은 명령 행을 단순화하고 특히를 제거하는 이점이 있습니다  -o. 관련된 표현을 찾기 -o가 어렵습니다. 네 잘못이야. Gilles의 답변과 같이 오류가 발생하지 않도록 명령이 수정 grep되면 .h파일 에서만 실행 됩니다 . 해야합니다 '(' -name '*.c' -o -name '*.h' ')'.
G-Man은 '복귀 상태 모니카'

답변:


18

주위에서 사용하는 작은 따옴표를 제거해야합니다 {}. 다음과 같이 명령을 단순화 할 수 있습니다.

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +

구식 GNU 찾기 버전을 사용하는 경우에도 여전히 작동합니다.

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;

죄송합니다. 백틱이 아닌 따옴표입니다.
David Kennedy

{}쉘에 특별한 의미가 없으므로 따옴표는 쓸모 가 없습니다.
jlliagre

find 매뉴얼 페이지에서 : "문자열 '{}'은 (는) 일부 버전의 find에서와 같이 단독 인 인수가 아닌 명령의 인수에서 발생하는 모든 위치에서 처리되는 현재 파일 이름으로 대체됩니다. 쉘에 의한 확장을 막기 위해 구조물을 이스케이프 처리 ( '\')하거나 인용해야 할 수도 있습니다. "
David Kennedy

1
나는 실제로 매뉴얼 페이지에서 그것을 읽었지만 사실은 중괄호를 인용해야한다는 것을 알고있는 껍질이 없다는 사실입니다. 어떤 쉘을 사용하고 있습니까?
jlliagre

세게 때리다. 따옴표가 있거나 없거나 어쨌든 오류가 발생합니다.
David Kennedy

10

"에 대한 인수 누락 -exec"은 일반적으로-에 대한 인수에 exec종결자가 누락 되었음을 의미합니다 . 터미네이터 중 단지 문자가 포함 된 인수 여야합니다 ;(그래서는 일반적으로 쓰여 쉘 명령에 인용 할 필요가, \;';'), 또는 포함 된 두 개의 연속 인수 {}+.

스테판 Chazelas가이 확인했습니다 당신이 지원하지 않는 GNU의 발견 이전 버전 사용하고 있는지 -exec … {} +만, -exec {} \;. GNU가 늦게 채택되었지만 git 및 훨씬 더 많이 포함하는 Cygwin 또는 git가 없지만 직원이 부족한 GNUwin32-exec … {} + 와 같은 덜 골동품적인 도구 모음을 얻는 것이 좋습니다. Cygwin이 제공하는 Linux를 사용하지만 우리는 임프레스 윈도우 분위기를 사용합니다. 이 기능은 9 년 전에 버전 4.2.12에 추가되었습니다 (GNU POSIX 호환 을 위해 마지막으로 확인 된 기능이었습니다 ).find

당신이 이전 GNU 찾기에 충실하려는 경우, 당신은 사용할 수 있습니다 -print0xargs -0임의의 파일 이름을 지원하고, 그룹화 명령 실행 : 비슷한 기능을 얻을 수 있습니다.

find a/folder b/folder -name '*.c' -o -name '*.h' -print0 | xargs -0 grep -I foobar /dev/null

find명령 행 에서 항상 와일드 카드를 인용하십시오 . 그렇지 않으면 .c파일이 포함 된 디렉토리에서이 명령을 실행 하면 인용되지 않은 파일이 현재 디렉토리 *.c.c파일 목록으로 확장됩니다 .

명령 행에 추가 /dev/null하는 것은 하나의 일치하는 항목을 찾 grep더라도 grep이 항상 파일 이름을 인쇄하도록하는 속임수 find입니다. GNU find에서 다른 방법은 옵션을 전달하는 것 -H입니다.


1
cygwin이 제공하는 나쁜 직원이 사용하기 위해 리눅스를 시도하지만 임 포즈 윈도우 분위기는 무엇을 의미합니까?
David Kennedy

GNUwin32는 기대하지 않습니다 :(
David Kennedy

질문에 대한 내 의견을 참조하십시오.
G-남자 '는 분석 재개 모니카'말한다

semi 주위의 따옴표는 package.json 스크립트 내에서 작동했습니다.
bvj

2

다음과 같은 명령이

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +

오류를 반환

find: missing argument to -exec

가능한 원인은 너무 오래된 GNU이므로 find구문을 지원하지 않습니다 -exec mycommand {} +. 이 경우 여러 대상을 수집 -exec mycommand {} \;하고 mycommand한 번만 실행하는 대신 발견 된 모든 대상에 대해 한 번만 실행 되는 낮은 성능의 교체가 실행 됩니다 mycommand.

그러나 GNU find는 다음을 지원하지 않습니다.

find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +

GNU find{} +보다 일반적인 대신 리터럴 조합 만 지원 하기 때문 {} additional parameters +입니다. 중괄호와 +문자 사이에는 아무 것도 없어야 합니다. 이 작업을 시도하면 동일한 오류가 발생합니다.

find: missing argument to -exec

해결 방법은 {} additional parameters \;작동하지만 찾은 모든 대상에 대해 한 번씩 명령을 실행하는 구문을 사용 하는 것입니다. GNU에서 더 많은 성능을 필요로하는 경우 find, 주어진 인수에 추가 매개 변수를 추가 할 수있는 랩퍼 스크립트를 작성해야합니다. 같은 것

#!/bin/bash
exec mycommand "$@" additional parameters

충분해야합니다. 또는 임시 파일을 만들지 않으려면 한 줄짜리 줄을 사용하여 다음과 같이 매개 변수의 순서를 변경할 수 있습니다.

find . -type f -and -name "*.ttf" -exec bash -c 'mycommand "$@" extra arguments' {} +

실행 mycommand {list of ttf files} extra arguments됩니다. -c플래그 뒤에 bash에 특수 문자를 두 번 이스케이프해야 할 수도 있습니다 .


(1) 실제로 질문에 대답하는 위의 부분은 다른 사람들에 의해 이미 주어졌습니다. (2) 당신이 묘사하는 것은 GNU의 결함이나 결함이 find아니라 POSIX에 의해 지정된 올바른 행동 입니다.
G-남자 '는 분석 재개 모니카'말한다

1
+1 마지막으로, 추가 매개 변수가 작동하지 않는 이유에 대한 답변을 제공하는 사람! POSIX 정의에 결함이있는 것 같습니다.
Jonathan

GNU find를 가지고 있다면 아마도 GNU가있을 것입니다 cp. 이 경우 실행 문자열 끝에 find ... -exec cp --target-directory ~/.fonts {} +를 유지할 수 {}있습니다.
roaima

1

find . -type f -perm 0777 -exec chmod 644 {}\;

오류가 발생했습니다 find: missing argument to ``-exec'.

사이에 공간을 추가 {}하고 \수정했습니다.

find . -type f -perm 0777 -print -exec chmod 644 {} \;


1
find해당 질문 의 명령 에는 그러한 문제가 없습니다 .
Kusalananda

질문에서, 나는 이해하지 못했습니다. 그러나 문제는 동일합니다.
ShreePool

@ Kusalananda 좋은 슬픔, 멍청한 놈은 질문의 제목과 본문 모두에 OP에 의해 명시된보고 된 오류에 대한 해결책을 제공했습니다.
bvj

@bvj이 질문 +은에 대한 -exec옵션 형식을 명시 적으로 처리 합니다 find. 이 답변은 사용자가 질문하지 않은 문제를 해결합니다.
Kusalananda

-1

과거에 exec 구문으로 두통을 겪었습니다. 이제는 더 좋은 bash 구문을 선호합니다.

for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done

각 파일이 순차적으로 평가되므로 파일을 그룹으로 취급하려는 경우 몇 가지 제한 사항이 있지만 출력을 다른 곳으로 파이프 할 수 있습니다


1
이것이 작동하는 경향이 있지만 이름에 공백이있는 파일을 올바르게 처리 할 수 ​​없기 때문에 순수 찾기 버전보다 유용성이 떨어집니다.
Etan Reisner

5
아니, 이러지 마 파일에 공백과 다른“이상한”문자가 포함 되 자마자 중단됩니다. 이 방법은보다 복잡하고 느리 find … -exec … \;므로 파일 이름이 길다는 것을 알고 있어도이를 사용할 이유가 없습니다.
Gilles 'SO- 악마 그만'

이것은 파일 이름을 기반으로 여러 줄의 논리를 실행 해야하는 상황에 도움이되었습니다 (문자 제거, 디렉토리 만들기 및 파일 이동과 같은). 한 번 exec에 여러 가지 일을하려고 하면 5 분 동안 너무 많은 두통을 겪었습니다. 내 파일 이름은 길
들였고
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.