GNU find -execdir 명령이 BSD find와 다르게 동작하는 이유는 무엇입니까?

GNU find -execdir 명령이 BSD find와 다르게 동작하는 이유는 무엇입니까?

내 OSX에서는 다음 find을 통해 기본 BSD와 함께 GNU를 설치했습니다.findbrew install findutils

내가 아는 한, BSD는 findPOSIX 표준을 따르며 GNU는 이를 선택 사항으로 만듭니다(이에 따르면우편 엽서), 이로 인해 예상되는 출력에 많은 불일치가 발생합니다.

예를 들어:

BSD 조회

$ find -L /etc -execdir echo {} ';' | head
etc
AFP.conf
afpovertcp.cfg
aliases
aliases.db
apache2
extra
httpd-autoindex.conf
httpd-dav.conf
httpd-default.conf

GNU 찾기

$ gfind --version
find (GNU findutils) 4.4.2
$ POSIXLY_CORRECT=1 gfind -L /etc -execdir echo {} ';' | head
/etc
/etc/AFP.conf
/etc/afpovertcp.cfg
/etc/aliases
/etc/aliases.db
/etc/apache2
/etc/apache2/extra
/etc/apache2/extra/httpd-autoindex.conf
/etc/apache2/extra/httpd-dav.conf
/etc/apache2/extra/httpd-default.conf
gfind: `echo' terminated by signal 13
gfind: `echo' terminated by signal 13
... endless loop here

-L참고: 위의 링크를 내 /etc링크 로 사용하고 있습니다 private/etc.

GNU find 매뉴얼에서 POSIX 표준을 따르도록 지정할 수 있다는 것을 알 수 있지만 POSIXLY_CORRECT위의 예에서는 이것이 작동하지 않습니다.

위의 예에서 GNU find가 동일한 출력을 갖도록 강제하는 다른 방법이 있습니까(예: POSIX 표준)?

무한 루프 외에도 GNU는 상대 파일 이름을 인쇄하는 반면 BSD는 전체 경로를 인쇄하는 이유는 무엇입니까?

답변1

이것은 아니다무한 루프, 이는 SIGPIPE를 사용하여 GNU가 사망을 find보고하는 것 입니다 echo(왜냐하면 stdout에 있는 파이프의 다른 쪽 끝은 head사망 시 닫혀 있었기 때문입니다).

-execdirPOSIX가 지정되지 않았습니다. 위해서 -exec라도 아무것도 없다POSIX 사양이는 명령이 SIGPIPE에 의해 종료되면 find종료되어야 함을 의미합니다.

-execdir따라서 POSIX 가 지정되면 gfindBSD보다 POSIX 규격이 더 높을 수 있습니다 find(질문에서 알 수 있듯이 하위 프로세스가 SIGPIPE로 종료될 때 BSD가 종료를 찾았다고 가정하면 FreeBSD는 find내 테스트에 포함되지 않았으며 실행됩니다).echo 루프 내각 파일에 대해(GNU find와 같이 무한하지 않음)).

가장 일반적인 경우에는 find하위 항목이 SIGPIPE로 인해 종료되면 종료하는 것이 더 낫다고 주장할 수 있지만, -exected 명령은 표준 출력에서 ​​파이프를 닫는 것 이외의 이유로 여전히 SIGPIPE로 인해 종료될 수 있으므로 종료하는 것이 find허용됩니다.

GNU를 사용하면 명령이 실패하면 find종료하도록 지시할 수 있습니다 .find

find . ... \( -exec echo {} \; -o -quit \)

find구현이 stderr에서 child-death 신호를 보고하는 것을 허용할지 아니면 허용하지 않을지 여부에 관해서 는 여기서(를 사용하여 -execdir) 어쨌든 POSIX의 범위를 벗어나지만 대신 -exec사용하면 -execdirgfind 비준수 사례가 될 것 같습니다.

사양은 다음과 find같이 말합니다."표준 오류는 진단 메시지에만 해당됩니다."뿐만 아니라거기에서 말했다:

기본 동작: 이 섹션이 "표준 오류는 진단 메시지에만 사용해야 합니다."로 나열되면 달리 명시하지 않는 한 종료 상태가 오류가 발생했음을 나타내는 경우에만 진단 메시지를 표준 오류로 보내야 함을 의미합니다. 유틸리티는 이 볼륨의 POSIX.1-2008에 설명된 대로 사용됩니다.

이는 find이 경우 0이 아닌 종료 상태가 반환되지 않으므로 stderr에 메시지를 출력해서는 안 된다는 것을 나타냅니다.

이 텍스트에 따르면 findGNU와 FreeBSD는 모두 다음 상황에서 비준수입니다.

$ find /dev/null -exec blah \;; echo "$?"
find: `blah': No such file or directory
0

둘 다 오류를 보고하지만 종료 상태를 0이 아닌 것으로 설정하지 않습니다. 그래서 내가이 질문은 austin-group(POSIX 뒤에 있는 사람들) 메일링 리스트에서 질문되었습니다..

명령을 다음과 같이 변경하면 참고하세요.

(trap '' PIPE; find -L /etc -execdir echo {} \; | head)

echo여전히 모든 파일에서 실행되고 여전히 실패하지만 이번에는 echo오류 메시지가 보고됩니다.


이제 filenamevs /etc/filenamevs 에 대한 내용 ./filename이 보여지고 있습니다.

-execdir다시 말하지만 ,기준옵션, 누가 옳고 그른지를 나타내는 텍스트가 없습니다. -execdir이는 BSD에 의해 소개되었고 find나중에 GNU에 의해 복사되었습니다 find.

GNU는 find의도적으로 일부 변경(개선)을 했습니다. 예를 들어 ./명령에 전달된 인수에 파일 이름을 추가합니다. 이는 find . -execdir cmd {} \;example로 시작하는 파일 이름에는 문제가 없음을 의미합니다.-

실제로 -L -execdir상위 디렉터리를 기준으로 파일 경로를 전달하지 않는 것은 실제로는허점GNU 버전 4.3.0~4.5.8에 영향을 미칩니다 find. 4.5.9에서 수정되었지만 개발 브랜치에 있었고 아직 새로운 브랜치가 없습니다.안정적인출판 이후(2015년 12월 22일 현재,임박한).

자세한 내용은 findutils 메일링 리스트를 참조하세요..

원하는 것이 Portable 각 파일의 기본 이름을 인쇄하는 것이라면 /etc다음과 같이 할 수 있습니다.

find -L /etc -exec basename {} \;

또는 더 효율적으로:

find -L ///etc | awk -F / '/\/\// && NR>1 {print last}
                          {if (NF > 1) last = $NF
                           else last = last "\n" $NF}
                          END {if (NR) print last}'

다음과 같이 단순화할 수 있습니다.

find -L /etc | awk -F / '{print $NF}'

파일 경로에 개행 문자가 포함되어 있지 않은지 확인할 수 있는 경우(IIRC, 일부 OS/X 버전은 /etc에 해당 파일이 있음)

GNUly:

find -L /etc -printf '%f\n'

여부에 관해서 :

find -exec echo {} \;

내부에협회POSIX를 언급하고 있습니까?

아니요, 명령 호출로서 이것은 POSIX가 아닙니다. ㅏ스크립트이는 비준수입니다.

POSIX에서는 find최소한 하나의 경로가 제공되어야 하지만 옵션이 아닌 첫 번째 인수가 or로 find시작하고 -술어 find(예 !: 또는 ()인 경우 지정되지 않은 동작이 유지되므로 GNU find동작이 유지 됩니다.호환성, 버그 보고(또는 조회 조건자를 나타내더라도 첫 번째 인수를 파일 경로로 처리) 또는 구현 얼굴에 빨간색 페인트를 뿌리는 등 그것이 동작에 POSIXLY_CORRECT영향을 미칠 이유가 없습니다 .find

관련 정보