nullglobВаріант (який до речі є 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), це взагалі скасувати команду, якщо глобус не відповідає.
bash(оскільки у версії 3) є failglobваріант для цього (цікаво для цієї дискусії, оскільки всупереч ashAT&T kshабо zsh, bashне підтримує локальні області застосування опцій (хоча це має змінитись у 4.4), цей варіант, коли включений у всьому світі, порушує декілька речей як функція доповнення bash).
Зверніть увагу , що CSH і Tcsh трохи відрізняється від zsh, fishабо bash -O failglobв таких випадках , як:
ls -- *.txt *.html
Там, де вам потрібно, щоб усі глобуси не відповідали команді, яку потрібно скасувати. Наприклад, якщо є один txt-файл і немає html-файлу, це стає:
ls -- file.txt
Ви можете отримати таку поведінку за zshдопомогою, setopt cshnullglobхоча більш розумним способом зробити це zshбуло б використовувати глобус на зразок:
ls -- *.(txt|html)
В zshі ksh93ви також можете застосувати nullglob на основі глобусу, що є набагато безпечнішим підходом, ніж зміна глобальної настройки:
files=(*.txt(N)) # zsh
files=(~(N)*.txt) # ksh93
створив би порожній масив, якщо немає txtфайлу замість помилки команди з помилкою (або зробити її масивом з одним *.txtбуквальним аргументом з іншими оболонками).
Версії fishдо 2.3 працювали б як, bash -O nullglobале попереджають, коли інтерактивні, коли глобус не відповідає. Починаючи з 2.3, він працює як zshкрім глобусів, які використовуються в for, setабо count.
Тепер, на замітці історії, поведінку насправді порушила оболонка Борна. У попередніх версіях Unix глобалізація здійснювалася через /etc/globhelper, і цей помічник поводився так csh: він би провалив команду, якщо жоден з глобусів не відповідав жодному файлу і не видалить глобус, не інакше.
Тож ситуація, в якій ми сьогодні, пояснюється поганим рішенням, прийнятим в оболонці Борна.
Зауважте, що оболонка Bourne (і оболонка C) оснащена ще однією новою функцією Unix: довкілля. Це означало змінне розширення (у попередника були лише $1, $2... позиційні параметри). Оболонка Bourne також ввела підстановку команд.
Ще одним поганим дизайнерським рішенням оболонки Борна було проведення глобалізації (і розщеплення) після розширення змінних та підстановки команд (можливо, для зворотної сумісності з оболонкою Томпсона, де echo $1все-таки можна було б викликати, /etc/globякщо $1містилися бідні символи (це було більше схоже на розширення макросу попереднього процесора) там, як у розгорнутому значенні, знову розбирався як код оболонки)).
Невдалі глобуси, які не відповідають, означають, наприклад, що:
pattern='a.*b'
grep $pattern file
не вдасться виконати команду (якщо a.whateverbв поточному каталозі немає деяких файлів). csh(який також виконує глобалізацію при змінному розширенні) не спрацьовує команда в цьому випадку (і я можу стверджувати, що це краще, ніж залишати спокійну помилку там, навіть якщо це не так добре, як не робити глобалізацію взагалі, як у zsh).