nullglob가 기본이 아닌 이유는 무엇입니까?


61

대부분의 쉘 nullglob에서 기본값이 아닙니다. 예를 들어이 명령을 실행하면

ls *

빈 디렉토리에서는 *글로브를 리터럴로 확장하고 *빈 인수 목록으로 확장합니다 . *빈 디렉토리에서 빈 인수 목록을 리턴하여보다 직관적 인 것처럼 보이 도록 해당 동작을 변경하는 방법이 있습니다 .

그렇다면 왜 nullglob기본적으로 비활성화되어 있습니까? 그렇다면 그 이유는 무엇입니까?


13
누군가는 한때 "우리는 항상 이런 식으로 해왔습니다"라는 잘못된 선택을했습니다. 소프트웨어 세계에서 유비쿼터스 현상은 아닙니다.
PSkocik

4
원래 그 이유는 nullglob 옵션이 그때 존재하지 않았기 때문입니다. 이전 버전과의 호환성을 유지하려면 기본적으로 비활성화되어 있어야합니다.
PM 2Ring

3
이 글에서는 널 글로브에 대해 구체적으로 언급하지는 않지만 글 로빙에 대한 일부 이력을 제공합니다. unix.stackexchange.com/a/136409/22724
StrongBad

4
nullglob이 기본적으로 활성화되어야한다는 것이 분명해야한다고 생각합니다. 나는 그것이 분명하지 않다고 생각합니다. 명령 호출 전에 쉘에서 확장이 발생한다는 것은 아무것도 확장하지 않는 것이 글로브가 변경되지 않은 상태보다 직관적이지 않은 동작이라는 것을 의미합니다.
kojiro

2
@kojiro 누구에게 덜 직관적입니까? * NIX 쉘에 대해 잘 알고있는 사람은 누구나이 글러브를 알고 *모든 기존 파일로 확장됩니다 . 빈 디렉토리 globs가 리터럴로 "확장"되는 특별한 경우가있는 것은 어떻게 "직관적" *입니까?
Kyle Strand

답변:


78

nullglob옵션 (BTW A는 zsh발명 만에 년 후 추가 bash(이 2.0경우 숫자에 적합하지 않을 것이다)). 그리고 ls좋은 예입니다 :

ls *.txt

또는 더 정확한 내용 :

ls -- *.txt

nullglobon을 사용하면 일치하는 파일이 없으면 (현재 디렉토리를 나열합니다) ls로 취급되는 인수없이 실행 됩니다 . 리터럴 을 인수로 ls -- .호출 ls하는 것보다 나쁩니다 *.txt.

대부분의 텍스트 유틸리티와 비슷한 문제가 있습니다.

grep foo *.txt

파일 foo이 없으면 stdin을 찾으십시오 txt.

보다 합리적인 기본값과 csh, tcsh, zsh 또는 fish 2.3+ (및 초기 Unix 쉘) 중 하나는 glob가 일치하지 않으면 명령을 모두 취소하는 것입니다.

bash(버전 3 이후)를 보유하고 failglob반대로 이후이 토론에 흥미가에 대한 옵션 (, ash, AT & T kshzsh, bash그) 4.4에서 변경 비록 (옵션에 대한 지역 범위를 지원하지 않는, 몇 가지를 깰 않습니다 전역 적으로 활성화하는 옵션을 bash-completion 함수와 같은).

그 CSH와 tcsh의이 약간 다릅니다 주 zsh, fishbash -O failglob같은 경우 :

ls -- *.txt *.html

명령을 취소하기 위해 모든 글롭이 일치하지 않는 곳. 예를 들어, txt 파일이 하나 있고 html 파일이 없으면 다음과 같이됩니다.

ls -- file.txt

당신과 그 동작을 얻을 수 zshsetopt cshnullglob그것을에서 할 수있는 더 합리적인 방법이 있지만 zsh같은 글로브를 사용하는 것입니다 :

ls -- *.(txt|html)

에서 zshksh93, 당신은 또한 적용 할 수 nullglob를 전역 설정을 수정하는 것보다 훨씬 더 온건 한 접근 방식은 당 글로브 기준에 :

files=(*.txt(N))  # zsh
files=(~(N)*.txt) # ksh93

txt오류가있는 명령을 실패하는 대신 파일 이 없으면 빈 배열을 만듭니다 (또는 *.txt다른 쉘이 있는 하나의 리터럴 인수가 있는 배열로 만듭니다 ).

fish2.3 이전 버전 은 작동 bash -O nullglob하지만 glob이 일치하지 않을 때 대화식 인 경우 경고를 표시합니다. 2.3부터는 , 또는에 zsh사용 된 glob를 제외하고 작동합니다 .forsetcount

역사 기록에서, 행동은 실제로 Bourne 쉘에 의해 깨졌습니다 . 이전 버전의 유닉스에서는 /etc/glob헬퍼 를 통해 글 로빙이 수행되었으며 헬퍼는 다음과 같이 작동 csh했습니다. 파일과 일치하는 글롭이 없으면 명령이 실패하고 일치하지 않는 글로브를 제거합니다.

오늘날 우리가 처한 상황은 Bourne 쉘의 잘못된 결정 때문입니다.

Bourne 쉘 (및 C 쉘)에는 또 다른 새로운 Unix 기능인 환경이 포함되어 있습니다. 그 의미 변수 확장 (그것의 전임자 만했다 $1, $2... 위치 매개 변수). Bourne 쉘은 또한 명령 대체를 도입했습니다.

Bourne 쉘의 또 다른 잘못된 디자인 결정은 변수 확장 및 명령 대체 (글로벌 카드 가 포함 된 경우 echo $1여전히 호출 할 수 있는 Thompson 쉘과의 하위 호환성) (글 로프 카드 매크로 확장과 유사 함 )에 대해 글 로빙 (및 분할)을 수행하는 것이 었습니다. 확장 된 값에서와 같이 셸 코드로 다시 구문 분석되었습니다))./etc/glob$1

일치하지 않는 글로브 실패는 예를 들어 다음을 의미합니다.

pattern='a.*b'
grep $pattern file

a.whateverb현재 디렉토리에 파일 이 없으면 명령이 실패합니다 . csh(변수 확장시 globbing을 수행함)은 그 경우 명령을 실패합니다 (그리고 나는 에서처럼 globbing을 수행하지 않는 것보다 좋지 않은 경우에도 휴면 버그를 남기는 것이 낫다고 주장합니다 zsh).


또 다른 유용성 문제가 있습니다 : nullglob탭 완성을 깨는 것처럼 보입니다 (탭 키를 누르면 활성화되어 있지 않습니다).
Kyle Strand

1
구문은 zsh만큼 우아하지는 않지만 bash 를 사용하여 glob 마다 nullglob를 사용할 수 있습니다.files=$(shopt -s nullglob;echo *.txt)
Jon Nalley

2
@JonNalley는 파일 이름의 연결 (공백 포함)을 (로 변환 가능 xpg_echo) 스칼라 변수로 저장합니다. 임의의 파일 이름으로 사용할 수 있으려면 4.4 이상 또는 GNU readarray -td '' files < <(shopt -s nullglob; printf '%s\0' *.txt)와 같은 것이 필요 합니다. 또는 여전히 bash4.4를 사용하는 경우 옵션의 로컬 범위에 25 년 후 재에서 복사 한 도우미 함수를 사용하십시오 . bash(shopt -s nullglob; printf '%s\0' *.txt) | xargs -r0 cmdxargslocal -
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.