이는 대부분의 쉘에서 nullglob
기본 설정이 아닙니다 . 이는 예를 들어 이 명령을 실행하면
ls *
빈 디렉토리에서는 빈 인수 목록 대신 *
glob을 텍스트로 확장 합니다. 빈 매개변수 목록이 빈 디렉토리에 반환 *
되도록 이 동작을 변경하는 방법이 있는데 , 이는 보다 직관적으로 보입니다.*
nullglob
그렇다면 기본적으로 비활성화되어 있는 이유가 있나요? 그렇다면 왜 그렇습니까?
답변1
nullglob
대부분의 경우 이 옵션은 이상적이지 않습니다. ls
좋은 예는 다음과 같습니다.
ls *.txt
또는 더 정확한 표현은 다음과 같습니다.
ls -- *.txt
.txt
( 유형을 제외하고 이름이 다음으로 끝나는 파일 나열)목차-d
해당 내용이 나열되어 있습니다. 아마도 특별한 대우를 피하기 위해 이 옵션을 사용하려고 할 것입니다.목차문서).
일치하는 파일이 없으면 on은 nullglob
인수 없이 실행되며 , 이는 (현재 디렉터리의 내용 나열) ls
로 처리되며 , 이는 리터럴을 인수로 호출하는 것보다 나쁠 수 있습니다.ls -- .
ls
*.txt
대부분의 텍스트 유틸리티에는 비슷한 문제가 있습니다.
grep foo *.txt
foo
파일이 없으면 표준 입력으로 검색이 수행됩니다 txt
.
csh, tcsh, zsh 또는 Fish 2.3+(및 이전 Unix 쉘)의 기본값인 보다 합리적인 기본값은 glob이 일치하지 않으면 명령을 완전히 취소하는 것입니다.
bash
(버전 3부터) 옵션이 있습니다 failglob
(이 논의는 ash
AT&T 와 달리 ksh
또는 반대로 옵션의 로컬 범위를 지원하지 zsh
않는 bash
3와 달리 전역적으로 활성화되면 bash-completion 기능과 같이 일부 기능이 중단되기 때문에 흥미롭습니다) .
zsh
csh와 tcsh는 다음과 같은 경우 fish
와 약간 다릅니다 .bash -O failglob
ls -- *.txt *.html
명령을 취소하려면 모든 전역 변수가 일치하지 않아야 합니다. 예를 들어 txt 파일은 있지만 html 파일은 없으면 다음과 같습니다.
ls -- file.txt
with 를 사용하여 이 동작을 얻을 수 있지만 zsh
보다 set -o cshnullglob
합리적인 접근 방식 zsh
은 다음과 같은 glob을 사용하는 것입니다.
ls -- *.(txt|html)
와 zsh
에서도 ksh93
신청할 수 있습니다.빈 공전역별로 보면 이는 전역 설정을 수정하는 것보다 더 합리적인 접근 방식입니다.
files=( *.txt(N) ) # zsh
files=( ~(N)*.txt ) # ksh93
파일이 없으면 txt
오류로 인해 명령이 실패하는 대신 빈 배열이 생성됩니다(또는 *.txt
다른 셸을 사용하여 하나의 리터럴 인수가 있는 배열로 만듭니다).
fish
2.3 이전 버전도 비슷하게 작동했지만 bash -O nullglob
상호작용할 때 glob이 일치하지 않으면 경고가 표시되었습니다. 2.3부터는 , zsh
또는 에서 사용된 glob과 다르게 작동합니다.for
set
count
역사적으로 이러한 행동은 실제로부서진Bourne 쉘로 구현됩니다. 이전 버전의 Unix에서는 와일드카드 지정이 /etc/glob
다음과 같이 작동하는 도우미를 통해 수행 되었습니다 csh
. 파일과 일치하는 와일드카드가 없으면 명령이 실패하고, 그렇지 않으면 일치하는 와일드카드가 제거되지 않습니다.
따라서 오늘날 우리가 있는 상황은 Bourne 쉘에서 내린 잘못된 결정 때문입니다.
Bourne 쉘(및 C 쉘)에는 또 다른 새로운 Unix 기능인 환경이 함께 제공됩니다. 이는 변수 확장을 의미합니다(이전 버전에는 $1
, $2
... 위치 인수만 있었습니다). Bourne 쉘에는 명령 대체도 도입되었습니다.
Bourne 쉘의 또 다른 잘못된 디자인 결정은 변수 확장 및 명령 대체에 와일드카드(및 분할)를 수행하는 것입니다(아마도 와일드카드가 포함된 경우 여전히 호출되는 Thompson 쉘과의 하위 호환성을 위해) echo $1
(전처리기 매크로와 비슷함) 확장) 확장 값이 다시 쉘 코드로 구문 분석되므로))./etc/glob
$1
예를 들어, 일치하지 않는 실패한 glob은 다음을 의미합니다.
pattern='a.*b'
grep $pattern file
명령이 실패하게 됩니다( a.whateverb
현재 디렉터리에 일부 파일이 없는 경우). (변수 확장 시에도 와일드카드를 수행합니다.) 이 경우에는 명령이 실패하게 만듭니다. ( // csh
처럼 와일드카드를 전혀 사용하지 않는 것만큼 좋지 않더라도 휴면 오류를 그대로 두는 것보다는 낫다고 생각합니다. .. ).rc
zsh
fish
shopt
내장 기능은 1996년 2.0에 추가되었으며 , zsh
해당 옵션 bash
의 이름을 따서 명명되었습니다.allow_null_glob_expansion
바꾸다이전 버전의 경우
² 해당 간격 내에 파일이 생성되지 않았거나 현재 디렉터리가 검색 가능하지만 읽을 수 없고 파일 또는 디렉터리가 존재하지 않는 한 ls
파일 없음 오류가 보고될 수 있습니다 . 예를 들어 시도한 후에*.txt
mkdir -p '*.txt/wtf'; chmod a=,u=wx .
set -o
3 버전 4.4에서는 Almquist 쉘에서처럼 옵션 세트를 로컬 함수로 설정할 수 있지만 두 번째 옵션 세트(옵션 세트 포함)에서는 local -
작동하지 않기 때문에 이와 관련하여 약간의 개선이 있었습니다.bash
shopt
답변2
nullglob
이 디자인은 void 매개변수가 제공될 때 void 결과를 생성하는 명령에 대해 기본값 사용을 고려하여 안전한 접근 방식을 취합니다 . 그러나 이 기본 동작은 다음과 같은 명령에는 적합하지 않을 수 있습니다 ls
. 스크립트에서는 유용할 수 있지만 다음과 같은 함수로 대체하지 nullglob
않는 한 완전히 안전하지는 않습니다 .ls
myls() { (($#)) && ls "$@" ; }
이렇게 하면 nullglob을 사용할 때 원하는 결과를 얻을 수 있습니다.
shopt -s nullglob
myls empty_directory/*
언어 기본값을 디자인할 때 우선순위는 예상치 못한 동작을 최소화하는 옵션을 채택하는 것입니다. 예측할 수 없는 동작보다 예외를 선호합니다.
nullglob
예측할 수 없는 입력 변경이 포함된 복잡한 스크립트를 도입하면 스크립트가 불안정해질 수 있다는 점에 유의하는 것이 중요합니다 . 실제로 이는 좋은 아이디어로 간주될 수 있지만 실제로는 예방 디버깅을 위해 추가 시간이 필요합니다.