nullglobOpcja (BTW to zshwynalazek, tylko dodaje lat później bash( 2.0)) nie byłby idealny w wielu przypadkach. I lsjest dobrym przykładem:
ls *.txt
Lub jego bardziej prawidłowy odpowiednik:
ls -- *.txt
Włączony nullglobdziałałby lsbez argumentu, który jest traktowany jako ls -- .(wyświetla bieżący katalog), jeśli żaden plik nie pasuje, co jest prawdopodobnie gorsze niż wywoływanie lsz literałem *.txtjako argumentem.
Miałbyś podobne problemy z większością narzędzi tekstowych:
grep foo *.txt
Będzie szukać foona stdin jeśli nie ma txtplików.
Bardziej sensownym ustawieniem domyślnym, a csh, tcsh, zsh lub fish 2.3+ (i wczesnych powłok uniksowych) jest całkowite anulowanie polecenia, jeśli glob nie pasuje.
bash(od wersji 3) ma na to failglobopcję (ciekawe w tej dyskusji, ponieważ w przeciwieństwie do ashAT&T kshlub zsh, bashnie obsługuje lokalnych zasięgów opcji (choć ma to zmienić w 4.4), ta opcja, gdy jest włączona globalnie, psuje kilka rzeczy jak funkcje kończące bash).
Zauważ, że csh i tcsh są nieznacznie różni się od zsh, fishlub bash -O failglobw przypadkach takich jak:
ls -- *.txt *.html
Gdzie potrzebujesz, aby wszystkie globusy się nie zgadzały, aby polecenie zostało anulowane. Na przykład, jeśli istnieje jeden plik txt i nie ma pliku html, staje się:
ls -- file.txt
Możesz uzyskać takie zachowanie za zshpomocą setopt cshnullglobbardziej rozsądnego sposobu, aby to zrobić, zshużywając globu takiego jak:
ls -- *.(txt|html)
W zshi ksh93możesz również zastosować nullglob dla poszczególnych globów , co jest o wiele zdrowszym podejściem niż modyfikowanie ustawień globalnych:
files=(*.txt(N)) # zsh
files=(~(N)*.txt) # ksh93
utworzyłby pustą tablicę, jeśli nie ma txtpliku, zamiast błędu polecenia (lub uczynienia go tablicą z jednym *.txtdosłownym argumentem z innymi powłokami).
Wersje fishwcześniejsze niż 2.3 działałyby jak, bash -O nullglobale dają ostrzeżenie, gdy są interaktywne, gdy glob nie pasuje. Od wersji 2.3 działa podobnie jak zshglobusy używane w for, setlub count.
Teraz, zgodnie z notatką historyczną, zachowanie zostało przerwane przez powłokę Bourne'a. We wcześniejszych wersjach Uniksa globowanie odbywało się za pomocą /etc/globpomocnika, który zachowywał się tak csh: nie wykonałby polecenia, jeśli żaden z globów nie pasowałby do żadnego pliku i nie usunąłby globów bez dopasowania.
Tak więc obecna sytuacja wynika z złej decyzji podjętej w powłoce Bourne'a.
Zauważ, że powłoka Bourne'a (i powłoka C) została dostarczona z inną nową funkcją uniksową: środowiskiem. Oznaczało to, że ekspansja zmienna (tylko jego poprzednik miał $1, $2... Parametry pozycyjne). Powłoka Bourne'a wprowadziła także zastępowanie poleceń.
Inną kiepską decyzją projektową powłoki Bourne'a było wykonanie globowania (i podziału) po rozwinięciu zmiennych i podstawianiu poleceń (być może dla wstecznej kompatybilności z powłoką Thompson, gdzie echo $1nadal wywoływałby się, /etc/globgdyby $1zawierał symbole wieloznaczne (bardziej przypominało to ekspansję makroprocesora przedprocesorowego) tam, jak w rozwiniętej wartości, został ponownie przeanalizowany jako kod powłoki)).
Niepowodzenie globów, które nie pasują, oznaczałoby na przykład, że:
pattern='a.*b'
grep $pattern file
nie powiedzie się polecenie (chyba że a.whateverbw bieżącym katalogu są jakieś pliki). csh(który wykonuje również globowanie po rozszerzeniu zmiennej) nie wykonuje polecenia w tym przypadku (i argumentowałbym, że jest to lepsze niż pozostawienie uśpionego błędu, nawet jeśli nie jest tak dobre, jak nie wykonywanie globowania w ogóle zsh).