Как избежать ошибок из-за нерасширенной звездочки


16

В bash я часто использую циклы for, такие как

for file in *.type; do 
  sommecommand "$file"; 
done;

выполнить операцию для всех подходящих файлов *.type. Если в рабочих каталогах не найдено ни одного файла с таким окончанием, звездочка не раскрывается, и обычно я получаю сообщение об ошибке, в котором говорится, что какая-то команда не нашла файл. Я могу сразу подумать о нескольких способах избежать этой ошибки. Но добавление условия не кажется слишком элегантным. Есть короткий и чистый способ достичь этого?

Ответы:


20

Да, выполните следующую команду:

shopt -s nullglob

это аннулирует совпадение, и никакая ошибка не будет вызвана.

  • если вы хотите, чтобы это поведение по умолчанию, добавьте команду в свой ~/.bashrc
  • если вы хотите обнаружить нулевой глобус в оболочке POSIX, попробуйте

    for i in *.txt; do
      [ "$i" = '*.txt' ] && [ ! -e '*.txt' ] && continue
    done

Смотрите http://mywiki.wooledge.org/NullGlob


1
Обратите внимание, что на самом деле возможно иметь файл с именем *.txt. Стоит проверить, существует ли файл.
Крис Даун

сообщение отредактировано соответственно.
Жиль Квено

@ChrisDown Обратите внимание, что здесь применяется тот же комментарий, что и к вашему ответу (с потенциально более серьезными последствиями из-за breakвместо continue).
Стефан Шазелас

6

В bash вы можете использовать shopt -s nullglobрасширение до пустого массива, если совпадений нет.

В оболочках POSIX без nullglob, вы можете избежать этой проблемы, проверив, что переданное имя файла действительно существует, имея [ -e "$file" ] || [ -L "$file" ] || continueв качестве первой части вашего forцикла.


1
Обратите внимание, что это не будет строго эквивалентно, поскольку [ -eвернет false для недоступных файлов или файлов, которые являются символическими ссылками на недоступные или несуществующие файлы.
Стефан Шазелас

@ StephaneChazelas, позвольте пунктам о символических ссылках быть признанными. Но что вы имеете в виду под «недоступными файлами»? Даже если я chmod 0 the_file, по- [ -e the_file ]прежнему оценивает верно, поэтому оно должно быть что - то еще.
Dubiousjim

1
представленное редактирование для обработки неработающих символических ссылок. надеюсь, что все в порядке.
Dubiousjim

2
@dubiousjim, mkdir -p x/{a,b} && chmod 444 x && echo x/* && [ -e x/a ]. x / a недоступен, но поскольку x читабелен, x / * будет расширяться.
Стефан Шазелас

@ StephaneChazelas, отлично, спасибо, что объяснили.
dubiousjim

4

Обычная техника для раковин, у которых нет nullglobвыбора,

set -- [*].type *.type
case $1$2 in
  '[*].type*.type') shift 2;;
  *) shift
esac
for file do
  cmd  -- "$file"
done

Дополнительным [*].typeявляется охват случая, когда *.typeв текущем каталоге вызывается один файл .

Теперь, если вы хотите включить точечные файлы, это становится более сложным .

Я полагаю, что эта техника была придумана Лорой Фэйрхед на Usenet несколько лет назад.


0

find . -name '*.type' -maxdepth 0 -exec somecommand "{}" ";"

Это полностью удаляет forцикл и глобус оболочки из уравнения. findвыполнит -execкоманду один раз за совпадение, и если совпадений нет, она никогда не будет выполнена. В -maxdepth 0инструктирует найти не рекурсию в подкаталоги с именем пути-аргумента ( .в данном случае).

Недостатком является то, что оно включает в себя другое приложение, хотя оно присутствует практически во всех системах Linux (и, вероятно, в большинстве Unixes).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.