В состоянии Bash if, как проверить, существуют ли какие-либо файлы, соответствующие простому шаблону?

Глупо, я использовал такое условие как часть скрипта:

if [ $(ls FOO* 2> /dev/null) ] # if files named "FOO*" were downloaded then echo "Files found" # ... process and email results else echo "Not found" # ... email warning that no files were found (against expectations) fi 

Это работает для нулевого и одного файла с именем FOO* , но сбой, если их больше одного . Из журналов я обнаружил несколько различных сообщений об ошибках, вытекающих из этого:

 [: FOO_20131107_082920: unary operator expected [: FOO_20131108_070203: binary operator expected [: too many arguments 

Мой вопрос: каков правильный способ проверки в if Bash if , существует ли один или несколько файлов, чье имя начинается с FOO ?

GNU bash, версия 4.2.25 (1) -release (x86_64-pc-linux-gnu)

3 Solutions collect form web for “В состоянии Bash if, как проверить, существуют ли какие-либо файлы, соответствующие простому шаблону?”

Это происходит потому, что ваша подстановка команды для ls выводит пробелы, и в конечном итоге она претерпевает расщепление слов перед передачей в [ . Менее прочным способом было бы поместить файлы в массив, а затем проверить, что в массиве есть хотя бы один член.

 shopt -s nullglob files=( FOO* ) if (( ${#files[@]} )); then # there were files fi 

Это работает потому, что (( по умолчанию возвращает true, если значение не равно 0, а ${#files[@]} получает количество элементов в массиве (которое будет> 0, если есть файлы, соответствующие glob).

Вы также можете сделать что-то подобное, если nullglob не установлен:

 if ls FOO* >/dev/null 2>&1; then # there were files fi 

Это просто проверяет код выхода ls , который будет равен 1, если вы передали имя файла, которого не существует (буква FOO* , если ничего не сопоставлено (если, конечно, вы не злы и есть файл с именем FOO* , и в этом случае он вернет 0 :-))).

Обратите внимание, что оба они также соответствуют каталогам. Если вы действительно хотите сопоставлять обычные файлы, вам необходимо проверить, что:

 for file in FOO*; do if [[ -f $file ]]; then # file found, do some stuff and break break fi done 

Многострочные ответы выше не соответствовали моему желанию однострочного решения и не изменяли окружающую среду. Вот общий однострочный вкладыш, который может работать на вас:

 echo $(ls FOO* 2>/dev/null | wc -w) 

/ dev / null – это потому, что ls выдает ошибку, если нет файла. Это просто игнорирует ls и подсчитывает количество найденных файлов на основе количества «слов» (действительно имен файлов). Вы можете использовать его в простой инструкции if:

 if [ 0 -lt $(ls FOO* 2>/dev/null | wc -w) ]; then echo "Some FOO is there." fi 

Этот подход имеет гибкость не только проверки наличия каких-либо совпадающих файлов, но и опциональной проверки того, сколько совпадающих файлов существует (просто измените 0 и / или -lt ), а затем продолжайте дальше.

Я не проверял файлы / папки, в которых есть подстановочные знаки или пробелы; Я подозреваю, что вышеупомянутый метод дал бы неправильный подсчет пробелов в частности, что является лишь проблемой, если требуется точный подсчет за пределами 0. Одно исправление, которое я пробовал для этого, – использовать $(ls -l FOO* 2>/dev/null | wc -l) , который разбивает список вниз по строкам и поэтому должен принимать больше белого.

Существует еще один вариант, используя случай ,

 FILES=FOO* FILES=$(echo $FILES) case $FILES in FOO\*) echo "Not found" ;; esac 

Это работает как случай, ожидающий проверки только одного аргумента.

  • Когда вы набираете «ls -a», каково значение «.» И «..»?
  • почему ls -d также перечисляет файлы и где они документируются?
  • Что означает список @ после каталога?
  • ls --color: как цветные исполняемые жесткие ссылки?
  • ls: показать размер файла с тысячами разделителей
  • Что означает * рядом с именем файла в выводе ls?
  • Разрешения cd и ls запрещены
  • Как перечислить только файлы в каталоге, разделенные запятыми
  • GeeXbox ls не показывает дату?
  • Разница между `ls -c` и` ls -t`
  • Как перечислять файлы с именем XXXmmyy.dat в естественном хронологическом порядке?
  • Linux и Unix - лучшая ОС в мире.