як поводитися з bash * match, коли немає відповідностей?


7

Наступний фрагмент bash чудово працює, коли *.txtв каталозі є фактично файли.

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

Коли їх немає, буквальне значення *.txtпотрапляє в цикл як $ txt (не добре).

Як змінити цей код, щоб, коли *.txtфайлів немає , do ... doneблок пропускався?


1
if [ "*.txt" != '*.txt' ] ; then do loop here ; fi
ott--

@ ott-- +1 для пропонування альтернативного рішення
kfmfe04

1
@ott: [ "*.txt" != '*.txt' ]завжди помилково - обидва рядки є лапками, тому жодна з них не перевіряється на відповідність. Якщо ви вилучите цитати з одного, у неї ... є інші проблеми.
Гордон Девіссон

@GordonDavisson +1 для вказівки на це: сценарій оболонки, здається, сповнений сюрпризів ...
kfmfe04

1
@GordonDavisson Дійсно, це повинно бути зроблено в 2 кроки до роботи: files=$(echo *.txt)а потім: if [ "${files}" != '*.txt' ] ; then.
ott--

Відповіді:


9

Схоже, Google відповів на це.

Поставте цей магічний заклик перед forтвердженням:

shopt -s nullglob

Майте на увазі, що це може викликати несподівані побічні ефекти для таких команд, як "ls * .txt"
noonex

4

Варіант nullglob (відповідь @ kfmfe04) найкращий, якщо ви використовуєте bash (не оболонку бренда-X), і вам не доведеться турбуватися про те, щоб змінити / зламати щось інше nullglob. В іншому випадку ви можете скористатися цією (трохи месиєвішою) опцією:

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

Це мовчки пропускає файли, які не існують (головним чином "* .txt", якщо не було відповідностей, але, можливо, також файли, які були видалені між тим, коли forстворений список і коли цикл потрапляв до них ...)


Файл може бути видалений між -eвикликом і пізнішою обробкою все ще ...
Костерер

@KoterWeather Правда, але тестування -eскорочує вікно часу, коли видалення є проблемою.
Гордон Девіссон,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.