GNU는 일부 쉘에 대해 {}을 찾아 마스킹합니다.


34

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. 

그것은 남자에서 find(GNU findutils) 4.4.2까지입니다.

이제 나는 이것을 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

그러나 그것은 맨 페이지가 말하는 것이 아닙니다. 그렇지 않습니까? 어떤 쉘 {}이 다른 방식으로 취급 됩니까?


@Volker Siegel : 편집이 의도적으로 발생했을 수 있지만 현재 찾기-수동을 확인하고 수정 한 내용이 잘못되었습니다. 또한 나쁜 습관 인 편집 내용을 요약 할 기회를 놓쳤으므로 변경 사항을 되돌립니다. 미안, 동료
사용자 알 수없는

오, 뭔가 부러 졌으면 다시 돌려 줘서 고마워 필자는이 "인쇄 인용 부호"를 렌더링 정의의 아티팩트로 생성하는 데 사용되는 매뉴얼 페이지 형식을 생성하는 텍스트 컴파일러를 기억하고있었습니다. 완벽한 인쇄 형식을 위해 TeX로 렌더링 할 수도 있습니다. 구문 강조 표시를 혼동했기 때문에 따옴표를 발견했습니다. 코드에서 사용될 때 특이한 첫 번째 인용 부호가 잘못되었다고 가정하고 여전히 가정합니다. 두 가지 변경 사항은 코드가 아니라 설명 텍스트에 있습니다. 우리가 그것들을 타이포그래피-미학적 렌더링으로 본다면 그것들은 옳습니다.
Volker Siegel

정보 출력 렌더링에서와 같이 양쪽에 동일한 인용 부호가 사용됩니다. 의심 할 여지없이 내 변경으로 인해 원본과 다른 점이 달라졌습니다. 그러나 문제가 있습니까? (저는 첫 번째 인용문을 사람 렌더링 정의의 버그로 간주합니다. 제가 아는 한 타이포그래피의 유일한 사례입니다.)
Volker Siegel

방금 확인했습니다 :`{} '명령 줄에서 작동하지 않습니다. 기술적으로는 정확하지만 의심하지 않는 사용자가 복사하여 붙여 넣을 때 이상한 오류가 발생하는 것을 좋아하지 않습니다.
Volker Siegel

@ VolkerSiegel : 코드가 아닌 산문 텍스트이므로 사용자는 여기에 무엇을 복사하여 붙여 넣습니까? 그리고 그것은 2011 년의 맨 페이지를 인용 한 것입니다. 나는 그 구절을 교정하여 어떤 점을 지적해야하는지에 대한 어떠한 가치도 보지 못했습니다. 주제가 충분히 복잡합니다. 이것이 귀하의 질문이라면, 나는 당신을 설득하려고하지 않고 맨 페이지를 정확하게 인용하려고하지만 내 질문에 대해서는 타협의 분위기에 있지 않습니다. 인용은 인용이다.
사용자 알 수 없음

답변:


26

요약 : 확장 된 쉘이 있었다면, 지금까지는 {}정말 오래된 유산입니다.

Bourne 쉘 및 POSIX 호환 쉘에서, 중괄호 ( {}) (달리 일반 문자입니다 ()같은 단어 구분 기호입니다 ;&[]문자를 글 로빙있다). 다음 문자열은 모두 문자 그대로 인쇄됩니다.

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

단일 중괄호로 구성된 단어는 예약어 이며 명령의 첫 번째 단어 인 경우에만 특별합니다.

Ksh는 Bourne 쉘과 호환되지 않는 확장으로 중괄호 확장을 구현합니다. 로 해제 할 수 있습니다 set +B. Bash는 이와 관련하여 ksh를 에뮬레이트합니다. Zsh는 괄호 확장도 구현합니다. set +I또는 setopt ignore_braces또는 로 끌 수 있습니다 emulate sh. 및 에 대한 인수에서 일반적으로 사용되므로 {}단어의 하위 문자열 인 경우에도 이러한 쉘 중 어느 것도 확장 되지 않습니다 .foo{}barfindxargs

단일 유닉스 v2

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

이 노트는 이후 버전의 표준에서 삭제되었습니다. 에 대한 예제find{} 와 마찬가지로 인용되지 않은 사용에 대한 예제가xargs 있습니다. {}인용해야 할 역사적인 Bourne 쉘이 있었을 지 모르지만 지금까지는 오래된 레거시 시스템 일 것입니다.

손에서 내가 가진 CSH 구현 (오픈 BSD 4.7, 데비안에 BSD의 CSH , tcsh의)는 모든 확장 {foo}foo있지만 떠나 {}혼자.


1
@geekosaur : 주석에서 작은 부분의 마크 다운 만 작동합니다 . 당신이 무슨 말을하는지 모르겠습니다. 이것이 ksh et al의 괄호 확장에 관한 것이라면,“Ksh는 괄호 확장을 호환되지 않는 확장으로 구현합니다”로 시작하는 단락을 읽으십시오.
Gilles 'SO- 악한 중지'

2
그랬습니다 bash(참조 $BASH_VERSION). 중괄호 확장은 매우 활기차고 훌륭합니다.
geekosaur

2
했다 지점. {}구문에서 유래 csh하지만, {}빈 문자열로 확장했다. 최신 포탄은 그것이 무의미하다는 것을 인식하지만 아직 오래된 csh것이 있습니다.
geekosaur

1
@geekosaur : 특정 플랫폼에서 어떤 특정 csh 버전을 말할 수 있습니까? 나는 그것을 직접 테스트하는 것을 선호하고 (리눅스에서 가능하다면) 그 사람이 직접 테스트한다는 것을 확신하고 싶다.
사용자가 알 수 없음

1
@geekosaur {}foo는로 확장 foo하지만 {}확장은 {}(백틱 내에서는 제외하지만 인용은 도움이되지 않음) 확장되며 문서화됩니다. 2BSD (첫 번째 릴리스), 2.79BSD, 2.8BSD 및 2.11BSD의 csh에 대해 확인했습니다.
Stéphane Chazelas

12

{}의 버전에 인용 될 필요가 fish3.0.0 이전에 쉘.

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

그리고 rc 쉘에서 (에도 akanga기반하고 rc있지만 es) :

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

이것들은 아마도 GNU가 문서를 작성했을 때 fish(2005 년에 텍스트 나 이와 비슷한 것이 이미 1994 년에 있었던 이후) 글을 썼을 때 GNU find documentation의 저자가 생각했던 rc쉘이 아니며 원래 유닉스 쉘이 아니 었습니다.

csh그것을 요구하는 몇몇 버젼 (버팀대 확장을 도입 한 쉘)에 대한 소문 이 있습니다. 그러나 csh2BSD 의 첫 번째 릴리스가 없었기 때문에 사람들에게 신용을주는 것은 어렵습니다 . 여기 PDP11 에뮬레이터에서 테스트 한대로 :

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

그리고 2BSDcsh매뉴얼 페이지에는 다음과 같이 명시되어 있습니다 .

특별한 경우`{ ',`}'및`{} '는 그대로 전달됩니다.

따라서 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확장 {}시 에만 확장 되므로 이러한 종류의 사용은 이식성이 없지만 ).


1

한마디로 csh. bash다른 현대 쉘은 사용자가 null 괄호 확장을 요구하지 않을 것임을 인식합니다. (현대 csh는 실제로 지금까지는 이상하게 tcsh처리 될 수 있습니다 {}.)


듣기 좋지만 반대쪽을 요구하고 있습니다.
사용자가 알 수 없음

리눅스 시스템이 모두 최신이기 때문에 누군가가 추가 정보 인용에 대한 정보 페이지의 참조를 제거한다고 가정합니다 csh. 모든 사람이 Linux에서 GNU 유틸리티를 실행하는 것은 아닙니다. 실제로 번들로 제공되는 명령이 제한된 구식 상용 Unix 시스템에 설치하는 것이 일반적입니다. (교체 csh시스템 스크립트는 원래의 특이성에 의존 할 수 있기 때문에 이러한 시스템에하는 것은 가능성이 적다 csh, 사용자가 모든 새를 사용하도록 구성된 경우에도 csh, root거의 확실하게 번들 버전을 유지해야합니다.)
geekosaur

2
아니요. 맨 페이지에 나와 있기 때문에 Wiki에서는 항상 "{}"을 (를) 사용하도록 조언해야한다고 말하는 사람과 논쟁 중입니다. 그리고 ksh, zsh, tcsh, csh 또는 XYZsh와 같이 내가 사용하지 않는 쉘이 있는지 알고 싶습니다.이 주장이 사실인지 또는 솔직히 가정 할 수 있는지 없습니다. "{}"이 (가) 필요한 다른 유닉스 용 쉘이 있다면, 왜 문장이 매뉴얼 페이지에 있는지에 대한 자세한 설명이 될 것입니다. 그러나 리눅스 초보자에게는 조언으로 적합하지 않습니다.
사용자 알 수 없음

경우 지금 궁금하네요 pdksh에 정답 있지만 ... 올바른 일을 아마 "진짜는 kshFOSS 요즘입니다".
geekosaur

4
mksh, ksh93, bash 및 zsh와 같은 Pdksh는 사이에 쉼표가 있거나 ( ..ksh93, bash 및 zsh의 경우) 중괄호 만 확장 합니다. 만 (t) CSH가 확장 {foo}foo, 심지어는 잎 {}(적어도 최근 BSD의에) 혼자.
Gilles 'SO- 악한 중지'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.