как обрабатывать совпадения bash *, когда совпадений нет?

2053
kfmfe04

Следующий фрагмент bash прекрасно работает, когда *.txtв каталоге действительно есть файлы.

for txt in *.txt do  echo "loading data from $txt" done  

Когда их нет, литерал *.txtпопадает в цикл как $ txt (не хорошо).

Как изменить этот код, чтобы при отсутствии *.txtфайлов do ... doneблок пропускался?

6
`if [" * .txt "! = '* .txt']; тогда сделайте цикл здесь; fi` ott-- 11 лет назад 1
@ ott-- +1 за предложение альтернативного решения kfmfe04 11 лет назад 0
@ott: `[" * .txt "! = '* .txt']` всегда ложно - обе строки заключены в кавычки, поэтому ни одна из них не проверяется на совпадения. Если вы удалите кавычки из одного он ... есть другие проблемы. Gordon Davisson 11 лет назад 1
@GordonDavisson +1 за указание на это: сценарии оболочки, похоже, полны сюрпризов ... kfmfe04 11 лет назад 0
@GordonDavisson Действительно, для работы нужно сделать 2 шага: `files = $ (echo * .txt)` и затем: `if [" $ "! = '* .Txt']; затем`. ott-- 11 лет назад 1
@ott: Это сработало бы (за исключением странного случая, когда есть один файл, который на самом деле называется «* .txt»). Gordon Davisson 11 лет назад 0
Кстати, можно сделать одной строкой: `if [" $ (echo * .txt) "! = '* .Txt')]; затем` John Hascall 6 лет назад 0

2 ответа на вопрос

8
kfmfe04

Похоже, у Google был ответ на этот вопрос.

Поместите это волшебное заклинание перед forутверждением:

shopt -s nullglob 
4
Gordon Davisson

Опция nullglob (ответ @ kfmfe04) лучше всего подходит, если вы используете bash (не оболочку brand-X), и вам не нужно беспокоиться о том, чтобы изменить / сломать nullglob. В противном случае вы можете использовать эту (немного более грязную) опцию:

for txt in *.txt do [ -e "$txt" ] || continue echo "loading data from $txt" done 

Это автоматически пропускает файлы, которые не существуют (в основном «* .txt», если совпадений не было, но, возможно, также файлы, которые были удалены между моментом forсоздания списка и моментом получения цикла ...)

Файл может быть удален между вызовом `-e` и последующей обработкой ... Koterpillar 6 лет назад 0
@Koterpillar Правда, но тестирование `-e` сокращает временное окно, в котором удаление является проблемой. Gordon Davisson 6 лет назад 0