Переключитесь на Bourne Again Shell ( /bin/bash
) из Bourne Shell ( /bin/sh
), и станет возможным простое решение.
На bash(1)
странице man упоминается опция nullglob :
Если установлено, bash позволяет шаблонам, которые не соответствуют ни одному файлу (см. Выше «Путь к имени» ), раскрываться в пустую строку, а не в себя.
В разделе «Расширение пути » написано:
После слов расщепления, ... Баш сканирует каждое слово для символов *, ? и [ . Если появляется один из этих символов, слово считается шаблоном и заменяется отсортированным по алфавиту списком имен файлов, соответствующих шаблону. Если не найдено подходящих имен файлов, а параметр оболочки nullglob не включен, слово остается без изменений. Если установлена опция nullglob и совпадений не найдено, слово удаляется.…
Итак, установка параметра nullglob дает желаемое поведение для шаблонов. Если ни один файл не соответствует шаблону, цикл не выполняется.
#!/bin/bash shopt -s nullglob for f in *.ext; do handle "$f" done
Но опция nullglob вполне может помешать желаемому поведению других команд. Таким образом, вы, вероятно, найдете целесообразным сохранить существующий параметр nullglob и восстановить его после этого. К счастью, shopt -p
встроенная команда выдает выходные данные в форме, которая может быть повторно использована в качестве входных данных. Но он выдает выходные данные для всех опций, поэтому используйте, grep
чтобы выбрать параметр nullobj . Смотрите журнал ниже (где $
указывает командную строку bash):
$ shopt -p | grep nullglob shopt -u nullglob $ shopt -s nullglob $ shopt -p | grep nullglob shopt -s nullglob
Итак, окончательный синтаксис bash для обработки нуля или более файлов, соответствующих шаблону подстановки, выглядит следующим образом:
#!/bin/bash SAVED_NULLGLOB=$(shopt -p | grep nullglob) shopt -s nullglob for f in *.ext; do handle "$f" done eval "$SAVED_NULLGLOB"
Также в вопросе упоминается несколько шаблонов, например:
for f in *.ext1 special.ext1 *.ext2; do ...
Параметр nullglob не влияет на слово в списке, которое не является «шаблоном», поэтому special.ext1
все равно будет передано в цикл. Единственное решение этого @Gordon Дэвиссон «s continue
выражение [ -e "$f" ] || continue
.
Выражение благодарности: на @Ignacio Vazquez-Abrams и @Gordon Davisson намекали bash(1)
и его опция nullglob . Спасибо. Поскольку они не сразу дали ответ с полностью проработанным примером, я делаю это сам.