GNU는 특정 셸에 대해 {}를 찾아 차단합니다. 어느 셸인가요?

GNU는 특정 셸에 대해 {}를 찾아 차단합니다. 어느 셸인가요?

GNU find의 매뉴얼 페이지에는 다음과 같은 내용이 나와 있습니다.

-exec command ;
    [...] 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. 

이것은 (GNU findutils) 4.4.2에 대한 man의 글입니다 find.

이제 bash와 dash로 이것을 테스트했는데 둘 다 {}차단할 필요가 없습니다. 간단한 테스트는 다음과 같습니다.

find /etc -name "hosts" -exec md5sum {} \; 

교정기를 덮는 데 꼭 필요한 덮개가 있나요? 발견된 파일에 공백(bash에서 호출됨)이 포함되어 있는지 여부에 따라 달라지지 않습니다.

find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \; 
/home/stefan/Ubuntu One

발견된 파일이 서브쉘로 전달되면 상황이 달라집니다.

find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d {}' \; 
ls: cannot access /home/stefan/Ubuntu: No such file or directory
ls: cannot access One: No such file or directory

이 문제는 다음을 통해 해결될 수 있습니다.

find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \;

비교해 보면:

find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \; 
/home/stefan/Ubuntu One

하지만 매뉴얼 페이지에서는 그런 내용을 다루지 않습니다. 그렇죠? 그렇다면 어떤 쉘이 {}이를 다르게 처리합니까?

답변1

일반화하다: 확장 가능한 쉘이 있었다면 {}이제는 정말 오래된 레거시입니다.

Bourne 쉘 및 POSIX 호환 쉘에서 중괄호( {})는 일반 문자입니다( 와일드카드 문자 (인 and )와 같은 단어 구분 기호인 and 와는 다름 ). 다음 문자열은 모두 문자 그대로 인쇄되어야 합니다.;&[]

$ echo { } {} {foo,bar} {1..3}
{ } {} {foo,bar} {1..3}

하나의 중괄호로 구성된 단어는 다음과 같습니다.예약어, 명령의 첫 번째 단어인 경우에만 특별합니다.

Ksh는 Bourne 셸의 호환되지 않는 확장으로 중괄호 확장을 구현합니다. 를 꺼서 이 작업을 수행할 수 있습니다 set +B. Bash는 이 점에서 ksh를 모방합니다. Zsh는 또한 중괄호 확장을 구현합니다. set +I또는 로 setopt ignore_braces끌 수 있습니다 emulate sh. 이러한 쉘은 인수에서 일반적으로 사용되는 것처럼 {}단어의 하위 문자열(예: )인 경우에도 어떤 경우에도 확장되지 않습니다.foo{}barfind그리고xargs.

단일 유닉스 v2눈치채다

일부 역사적 시스템에서는 중괄호가 제어 연산자로 간주됩니다. 향후 표준화 활동을 지원하려면 이식 가능한 응용 프로그램에서는 문자 자체를 나타내기 위해 인용되지 않은 중괄호를 사용하지 않아야 합니다. ISO/IEC 9945-2:1993 표준의 향후 버전에서는 이를 요구할 수 {있으며 토큰은 자주 사용되는 구성으로 인해 특별한 경우가 면제될 수 있지만 }제어 연산자로 별도로 처리할 수 있습니다.{}find {}

이 참고 사항은 이 표준의 후속 버전에서 제거되었습니다.의 예find{}다음과 같이 인용되지 않은 목적이 있습니다 .의 예xargs. {}역사적인 Bourne 쉘을 참조 해야 할 수도 있지만 이제는 매우 오래된 레거시 시스템입니다.

내가 갖고 있는 csh 구현(OpenBSD 4.7,데비안의 BSD csh, tcsh) 모두 확장 {foo}되었지만 무시 foo되었습니다 {}.

답변2

3.0.0 이전의 쉘 버전에서는 인용이 필요합니다 {}.fish

$ fish -c 'echo find -exec {} \;'
find -exec  ;

rc 셸에서(또한 akanga기반이지만 rc은 아님 es):

$ rc -c "echo find -exec {} ';'"
line 1: syntax error near '{'

fish이 쉘 은 2005년에 처음 출판되었으며(이 텍스트 또는 이와 유사한 텍스트는 1994년에 존재함) rc원래 Unix 쉘이 아니었기 때문에 GNU 문서 작성자가 이 텍스트를 작성할 때 염두에 두었던 쉘이 아닐 수도 있습니다 .

csh일부 버전 (중괄호 확장을 도입한 쉘)이 이를 필요 로 한다는 소문이 있습니다 . 그러나 csh2BSD의 첫 번째 버전에서는 그렇지 않았기 때문에 이러한 크레딧을 제공하기가 어렵습니다 . PDP11 에뮬레이터의 테스트는 다음과 같습니다.

# echo find -exec {} \;
find -exec {} ;

게다가2BSD 매뉴얼 페이지에는 csh다음과 같이 명확하게 나와 있습니다.:

특수한 경우로 "{", "}" 및 "{}"는 중단 없이 전달됩니다.

따라서 나중에 csh 또는 tcsh의 후속 버전에서 이 문제가 발생하면 놀랄 것입니다.

일부 버전에서는 일부 버그를 수정하는 것일 수도 있습니다. 여전히 2BSD csh를 사용하고 있습니다(2.79BSD, 2.8BSD, 2.11BSD에서도 동일):

# csh -x
# echo foo {} bar
echo foo {} bar
foo {} bar
# echo `echo foo {} bar`
echo `echo foo {} bar`
echo foo {} bar
foo  bar

그러나 그 인용문은 도움이 되지 않습니다:

# echo `echo foo '{}' bar`
echo `echo foo '{}' bar`
echo foo {} bar
foo  bar

전체 명령 대체를 인용할 수 있습니다.

# echo "`echo foo {} bar`"
echo `echo foo {} bar`
echo foo {} bar
foo {} bar

하지만 이는 외부 에코에 매개변수를 전달하는 것입니다.

csh또는 에서는 다음과 같이 개별적으로 대신 tcsh인용해야 합니다 .{}

find . -name '*.txt' -type f -exec cp {} '{}.back' \;

(이 find사용법은 이식성이 없습니다. 일부는 개별적으로 확장될 때만 확장되기 때문입니다 find. {})

답변3

즉, csh. bash그리고 다른 최신 쉘은 사용자가 빈 중괄호 확장이 필요하지 않을 수도 있음을 인식합니다. ( csh실제로 현대에서는 tcsh아마도 {}여전히 이 문제를 분별있게 처리할 수 있을 것입니다.)

관련 정보