Проверьте, существует ли файл с подстановочным знаком в сценарии оболочки

Я пытаюсь проверить, существует ли файл, но с подстановочным знаком. Вот мой пример:

if [ -f "xorg-x11-fonts*" ]; then
    printf "BLAH"
fi

Я тоже пробовал без двойных кавычек.


person Danny    schedule 15.06.2011    source источник
comment
Две ошибки в вашем коде: (1) звездочка должна находиться за пределами двойных кавычек (звездочка в кавычках теряет свое специальное значение подстановочного знака) и (2) если несколько файлов соответствуют шаблону, команде [ будет передано несколько аргументов, скорее всего, вызов [ завершится с ошибкой и, следовательно, будет интерпретирован как отсутствие соответствия файлов.   -  person Richard Hansen    schedule 17.06.2011


Ответы (21)


Обновление: для сценариев bash наиболее прямой и эффективный подход:

if compgen -G "${PROJECT_DIR}/*.png" > /dev/null; then
    echo "pattern exists!"
fi

Это будет работать очень быстро даже в каталогах с миллионами файлов и не требует новой подоболочки.

Источник


Самый простой - полагаться на возвращаемое значение ls (оно возвращает ненулевое значение, если файлы не существуют):

if ls /path/to/your/files* 1> /dev/null 2>&1; then
    echo "files do exist"
else
    echo "files do not exist"
fi

Я перенаправил вывод ls, чтобы сделать его полностью бесшумным.


РЕДАКТИРОВАТЬ: поскольку этому ответу уделялось немного внимания (и очень полезные замечания критиков в виде комментариев), вот оптимизация, которая также полагается на расширение глобуса, но избегает использования ls:

for f in /path/to/your/files*; do

    ## Check if the glob gets expanded to existing files.
    ## If not, f here will be exactly the pattern above
    ## and the exists test will evaluate to false.
    [ -e "$f" ] && echo "files do exist" || echo "files do not exist"

    ## This is all we needed to know, so we can break after the first iteration
    break
done

Это очень похоже на ответ @ grok12, но позволяет избежать ненужной итерации по всему списку.

person Costi Ciudatu    schedule 15.06.2011
comment
Предупреждение: в Debian Almquist Shell (dash), установленном в /bin/sh в Debian и Ubuntu, &>, похоже, отбрасывает код выхода, и это нарушает это решение. Обходной путь - вместо этого перенаправить с помощью > /dev/null 2>&1. - person qerub; 20.11.2011
comment
ls может работать довольно медленно в каталоге с большим количеством файлов (вероятно, из-за сортировки). По крайней мере, вы можете отключить сортировку с помощью -U. - person musiphil; 22.06.2012
comment
Было бы лучше перечислить файлы в текстовый файл и посмотреть на него, если бы вы выполняли много поисков? - person Mike Q; 13.06.2014
comment
@musiphil Спасибо за вклад. Я отредактировал ответ, чтобы добавить оптимизированную альтернативу, исключающую использование ls. - person Costi Ciudatu; 27.09.2014
comment
@CostiCiudatu вы проверили, как эта альтернатива работает, когда в имени каталога есть пробелы? Не будет, например, for f in /path/to/your files* интерпретируется как два аргумента, /path/to/your и files*? Я пробовал заключать в двойные кавычки, но это не сработало (файл никогда не находит, даже если он есть). - person Izzy; 14.12.2014
comment
@ Иззи, вы должны заключить это в двойные кавычки, но оставьте * снаружи: for f in "/path/to/your files"* должно работать. - person Costi Ciudatu; 14.12.2014
comment
@CostiCiudatu подтверждено, спасибо! Возможно, вы захотите включить это в свой ответ, чтобы его было легче найти :) Тем временем я остановился на ответе Панкаджа - но хорошо чтобы узнать альтернативу :) - person Izzy; 14.12.2014
comment
Предупреждение. Это не удастся, если в каталоге много файлов. Расширение * превысит ограничение на длину командной строки. - person Chris Cogdon; 30.07.2016
comment
@CostiCiudatu, однако, он все равно не сработает, если в самих файлах есть пробелы в их именах, не так ли? - person Fabio A.; 25.11.2016
comment
Я опубликовал решение, которое не требует ни for циклов, ни каких-либо внешних инструментов, и работает с именами файлов, содержащими пробелы: stackoverflow.com/ a / 40808284/566849 - person Fabio A.; 25.11.2016
comment
Одно замечание ... Не все боксы linux / unix поддерживают glob. Например, один из серверов unix на моей работе не поддерживает glob. - person Sometowngeek; 17.09.2018
comment
Второй вариант без условного первого не будет работать при включенном set -e (часто включается в системах сборки, чтобы bash немедленно завершал работу при ошибках). В этом случае сценарий может нежелательно дать сбой при обнаружении цикла for. - person Jonathan Komar; 04.11.2019
comment
unix.stackexchange.com/questions/128985/ - person qwr; 22.01.2020
comment
Используйте 1_ - person Theodore R. Smith; 15.10.2020
comment
compgen -G, похоже, не совсем поддерживает расширенные шаблоны глобусов. Не работает с compgen -G "*.{ts,go,json}". То есть логика подстановки -G и логика подстановки фактическая не всегда одинаковы (по крайней мере, без дополнительной заботы?). Кажется хрупким. - person Dr. Jan-Philip Gehrcke; 08.12.2020
comment
@ TheodoreR.Smith Мне неудобно брать на себя ответственность за ваше потрясающее решение, поэтому, пожалуйста, подумайте о том, чтобы отменить ваше изменение и сделать это своим собственным ответом или комментарием вместо редактирования старого принятого ответа. - person Costi Ciudatu; 08.12.2020

Если в вашей оболочке есть параметр nullglob и он включен, шаблон подстановки, не соответствующий файлам, будет полностью удален из командной строки. Это приведет к тому, что ls не увидит аргументов пути, выведет список содержимого текущего каталога и завершится успешно, что неверно. GNU stat, который всегда терпит неудачу, если не заданы аргументы или аргумент, указывающий на несуществующий файл, был бы более надежным. Кроме того, оператор перенаправления &> - это треп.

if stat --printf='' /path/to/your/files* 2>/dev/null
then
    echo found
else
    echo not found
fi

Еще лучше GNU find, который может обрабатывать поиск с использованием подстановочных знаков внутренне и завершать работу, как только найдет один подходящий файл, вместо того, чтобы тратить время на обработку потенциально огромного их списка, расширенного оболочкой; это также позволяет избежать риска переполнения буфера командной строки оболочкой.

if test -n "$(find /dir/to/search -maxdepth 1 -name 'files*' -print -quit)"
then
    echo found
else
    echo not found
fi

В версиях find, отличных от GNU, может не быть параметра -maxdepth, используемого здесь, чтобы find выполнял поиск только по / dir / to / поиск, а не все дерево каталогов, укоренившееся там.

person flabdablet    schedule 09.10.2011
comment
Лучше всего разрешить find обрабатывать подстановочный знак, потому что bash, расширяя шаблон, пытается отсортировать список совпадающих имен файлов, что расточительно и может быть дорогостоящим. - person musiphil; 22.06.2012
comment
@musiphil Запуск внешнего процесса, такого как find, еще более расточителен, если в каталоге всего несколько файлов (или ни одного). - person dolmen; 24.02.2017
comment
@dolmen: Вы правы. Думаю, все зависит от ситуации; с другой стороны, если файлов очень много, расширение bash с подстановочными знаками может занять больше времени, чем запуск find. - person musiphil; 13.03.2017
comment
@musiphil Еще хуже: при большом количестве подстановочных знаков расширение может просто не сработать. Но в этом случае расширение огромного вывода find, вероятно, тоже не удастся. Также обратите внимание, что перечисление всех файлов с помощью find только для того, чтобы затем проверить, является ли этот вывод пустым или нет, является большой тратой ресурсов. - person dolmen; 13.04.2017
comment
Команда find создает неприятное сообщение об ошибке, если файлы не найдены: find: '/dir/to/search': No such file or directory; Вы можете подавить это с помощью -quit 1> /dev/null 2>&1 - person rubo77; 23.04.2017
comment
@dolmen: Запуск find с -quit, как описано в сообщении @flabdablet, не повлияет на огромное количество файлов, потому что он завершает работу, как только находит первое совпадение, и, следовательно, не выводит список всех файлов. Так что это не такая большая трата ресурсов, как вы предлагаете. Более того, find не просто расширяет подстановочный знак, как это делает оболочка, но проверяет каждый найденный файл на соответствие шаблону, чтобы убедиться в том, что он не дает сбоев для огромного количества файлов. - person musiphil; 25.04.2017

Вот мой ответ -

files=(xorg-x11-fonts*)

if [ -e "${files[0]}" ];
then
    printf "BLAH"
fi
person Pankaj Parashar    schedule 01.07.2013
comment
Вы должны добавить unsetopt nomatch, если zsh сообщает об ошибках. - person Chih-Hsuan Yen; 03.01.2015
comment
и shopt -s nullglob для bash - person nhed; 28.06.2016
comment
Возможно, следует более четко указать, что использование массива явно не соответствует POSIX sh. - person tripleee; 26.09.2017
comment
@nhed: да, хотя бы для выявления патологического случая файла с именем xorg-x11-fonts*. В противном случае -e позаботится о проверке (нерасширенный xorg-x11-fonts* не пройдёт проверку). - person kkm; 15.02.2020
comment
Тест должен быть ${files[0]-}, что в точности совпадает с ${files-}. В противном случае, если звездочки выровнены неудачно так, что действуют как set -u, так и shopt -s nullglob, расширение не удастся. - person kkm; 15.02.2020

Вы можете сделать следующее:

set -- xorg-x11-fonts*
if [ -f "$1" ]; then
    printf "BLAH"
fi

Это работает с sh и производными: ksh и bash. Он не создает суб-оболочки. Команды $ (..) и `...`, используемые в других решениях, создают вспомогательную оболочку: они разветвляют процесс и неэффективны. Конечно, он работает с несколькими файлами, и это решение может быть самым быстрым или вторым после самого быстрого.

Это тоже работает, когда нет совпадений. Как сказал один из комментаторов, нет необходимости использовать nullglob. $ 1 будет содержать исходное имя теста, поэтому test -f $ 1 не будет успешным, потому что файл $ 1 не существует.

person joseyluis    schedule 22.12.2016
comment
Самое портативное решение! - person dolmen; 24.02.2017
comment
Увы, когда нет совпадений, не работает. $ 1 будет содержать исходное имя теста, включая *. Вы можете установить nullglob в bash, чтобы он БУЛ. Но это не переносимо :) - person Chris Cogdon; 09.03.2018
comment
Крис, когда совпадений нет, $ 1 будет содержать исходное имя теста, включая *, как вы говорите. Тогда проверка: [-f $ 1] не будет успешной, потому что файл * не существует. Поэтому вам не нужны nullglob или другие уловки. Это 100% портативный. - person joseyluis; 16.05.2018
comment
Пробовал использовать zsh как оболочку. Он работает, если набирается как команда, но не работает с ошибкой «совпадений не найдено» при вызове из zsh-скрипта. (Как ни странно) - person jmary; 29.05.2019
comment
jmary: Какую команду set вы использовали? Какой-то особенный персонаж? - person joseyluis; 29.05.2019

for i in xorg-x11-fonts*; do
  if [ -f "$i" ]; then printf "BLAH"; fi
done

Это будет работать с несколькими файлами и с пробелами в именах файлов.

person grok12    schedule 18.06.2011
comment
Он напечатает несколько BLAH, если есть несколько совпадений. Может быть, добавить break для выхода из цикла после первого совпадения. - person tripleee; 27.05.2016
comment
Это (с перерывом @tripleee) получает мой голос. Благодаря использованию только встроенных подстановок и оператора проверки файлов, он позволяет даже не поднимать вопрос о крайних случаях, связанных с использованием таких команд, как ls или find, или от пересылки глобусов. Я думаю, что в нем нет всех проблем, таких как имена с пробелами, настройка nullglob и bashisms, которые были подняты для некоторых других ответов. Я сделал это функцией: existsAnyFile () { for file; do [ -f "$file" ] && return 0; done; false; } - person sdenham; 30.06.2016
comment
Обратите внимание, что это приводит к ошибке статистики, если xorg-x11-fonts * не существует, что, вероятно, не то, что вам нужно. - person rfay; 09.11.2018

ОБНОВЛЕНИЕ:

Хорошо, теперь у меня определенно есть решение:

files=$(ls xorg-x11-fonts* 2> /dev/null | wc -l)
if [ "$files" != "0" ]
then
   echo "Exists"
else
    echo "None found."
fi

> Exists
person Swift    schedule 15.06.2011
comment
В моей оболочке (zsh) он работает, если есть только одно совпадение с глобусом, в противном случае он расширяет все файлы и тест не выполняется (слишком много аргументов). - person Edward Thomson; 16.06.2011
comment
Обновите мой код. Я уверен, что это работает, я только что установил zsh и протестировал. - person Swift; 16.06.2011
comment
ls может работать довольно медленно в каталоге с большим количеством файлов (вероятно, из-за сортировки). По крайней мере, вы можете отключить сортировку с помощью -U. - person musiphil; 22.06.2012
comment
Если подстановка совпадает с именем каталога, ls выдаст содержимое этого каталога, что может вызвать ложные срабатывания. - person William Everett; 22.03.2016
comment
Для запуска ls и wc требуется запустить две внешние программы. Совершенно неэффективно. - person dolmen; 24.02.2017

Может быть, это кому-то поможет:

if [ "`echo xorg-x11-fonts*`" != "xorg-x11-fonts*" ]; then
    printf "BLAH"
fi
person Marian    schedule 07.01.2014
comment
Это самый простой, легкий и элегантный ответ, который действительно работает! - person Serge Stroobandt; 28.06.2015
comment
@SergeStroobandt Не уверен, что согласен. Здесь может потребоваться подмена команд, но это вызывает у меня рефлекс съеживания. - person tripleee; 27.05.2016
comment
да ... а что если файл с буквальным именем xorg-x11-fonts\* существует? - person mlathe; 12.10.2016
comment
Совсем не элегантно, потому что он создает вспомогательную оболочку для запуска команды echo. - person dolmen; 24.02.2017
comment
Считаю это решение хорошим при поиске файлов с расширениями * .MIF. - person Faris; 12.02.2021

Вопрос не был специфическим для Linux / Bash, поэтому я подумал, что добавлю способ Powershell, который обрабатывает подстановочные знаки по-разному - вы помещаете его в кавычки, как показано ниже:

If (Test-Path "./output/test-pdf-docx/Text-Book-Part-I*"){
  Remove-Item -force -v -path ./output/test-pdf-docx/*.pdf
  Remove-Item -force -v -path ./output/test-pdf-docx/*.docx
}

Я думаю, что это полезно, потому что концепция исходного вопроса охватывает «оболочки» в целом, а не только Bash или Linux, и применима также к пользователям Powershell с тем же вопросом.

person Jeremy Hajek    schedule 13.09.2015
comment
даже более актуально сейчас, когда pwsh - вещь. - person Chaim Eliyah; 17.01.2020

Строго говоря, если вы хотите напечатать только «Blah», вот решение:

find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 'BLAH' -quit

Вот еще один способ:

doesFirstFileExist(){
    test -e "$1"
}

if doesFirstFileExist xorg-x11-fonts*
then printf "BLAH"
fi

Но я думаю, что наиболее оптимальным является следующее, потому что он не пытается сортировать имена файлов:

if [ -z `find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 1 -quit` ]
then printf "BLAH"
fi
person Vouze    schedule 26.10.2016
comment
Вы также можете использовать -exec вариант поиска, например: find . -maxdepth 1 -name '*.o' -exec rm {} \; - person user3405291; 14.03.2018

Вот решение вашей конкретной проблемы, которое не требует for циклов или внешних команд, таких как ls, find и т.п.

if [ "$(echo xorg-x11-fonts*)" != "xorg-x11-fonts*" ]; then
    printf "BLAH"
fi

Как видите, это немного сложнее, чем вы надеялись, и полагается на тот факт, что, если оболочка не может расширить глобус, это означает, что файлы с этим глобусом не существуют, и echo выведет glob < em> как есть, что позволяет нам проводить простое сравнение строк, чтобы проверить, существует ли вообще какой-либо из этих файлов.

Однако, если мы будем обобщать процедуру, мы должны принять во внимание тот факт, что файлы могут содержать пробелы в своих именах и / или путях и что glob char может по праву расширяться до нуля (в вашем примере это будет случай файла с именем в точности xorg-x11-fonts).

Этого можно добиться с помощью следующей функции в bash.

function doesAnyFileExist {
   local arg="$*"
   local files=($arg)
   [ ${#files[@]} -gt 1 ] || [ ${#files[@]} -eq 1 ] && [ -e "${files[0]}" ]
}

Возвращаясь к вашему примеру, его можно было бы вызвать так.

if doesAnyFileExist "xorg-x11-fonts*"; then
    printf "BLAH"
fi

Расширение глобуса должно происходить внутри самой функции, чтобы она работала должным образом, поэтому я заключил аргумент в кавычки, и именно для этого предназначена первая строка в теле функции: так что любые несколько аргументов (которые могут быть результатом глобуса расширение вне функции, а также ложный параметр) будут объединены в один. Другой подход может заключаться в выдаче ошибки при наличии более одного аргумента, а другой может заключаться в игнорировании всех аргументов, кроме 1-го.

Вторая строка в теле функции устанавливает files var в массив, состоящий из всех имен файлов, до которых расширяется глобус, по одному для каждого элемента массива. Это нормально, если имена файлов содержат пробелы, каждый элемент массива будет содержать имена как есть, включая пробелы.

Третья строка в теле функции выполняет две функции:

  1. Сначала он проверяет, есть ли в массиве более одного элемента. Если это так, это означает, что глобус наверняка был расширен до чего-то (из-за того, что мы сделали в первой строке), что, в свою очередь, означает, что существует хотя бы один файл, соответствующий глобу, а это все, что мы хотели. знать.

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

person Fabio A.    schedule 25.11.2016
comment
Это неэффективно, потому что $(..) запускает вспомогательную оболочку. - person dolmen; 24.02.2017
comment
@dolmen суб-оболочка - это такой же процесс, как и любой другой. Принятый ответ запускает команду ls, которая для всех целей и задач столь же эффективна (или неэффективна), как и вспомогательная оболочка. - person Fabio A.; 28.03.2017
comment
Я никогда не писал, что принятый ответ лучше и что я бы согласился, если бы был отправителем. - person dolmen; 13.04.2017
comment
Обратите внимание, что обобщенный метод, который я объясняю в том же ответе, вообще не использует подоболочки. - person Fabio A.; 13.04.2017

Код на bash, который я использую

if ls /syslog/*.log > /dev/null 2>&1; then 
   echo "Log files are present in /syslog/; 
fi

Спасибо!

person CapitanBlack    schedule 12.04.2016

Нашел пару интересных решений, которыми стоит поделиться. Первый по-прежнему страдает от проблемы «это сломается, если будет слишком много совпадений»:

pat="yourpattern*" matches=($pat) ; [[ "$matches" != "$pat" ]] && echo "found"

(Напомним, что если вы используете массив без синтаксиса [ ], вы получаете первый элемент массива.)

Если в вашем скрипте есть «shopt -s nullglob», вы можете просто сделать:

matches=(yourpattern*) ; [[ "$matches" ]] && echo "found"

Теперь, если в каталоге может быть тонна файлов, вы в значительной степени застряли в использовании find:

find /path/to/dir -maxdepth 1 -type f -name 'yourpattern*' | grep -q '.' && echo 'found'
person Chris Cogdon    schedule 09.03.2018

Использование новых причудливых функций shmancy в оболочках ksh, bash и zsh (в этом примере не обрабатываются пробелы в именах файлов):

# Declare a regular array (-A will declare an associative array. Kewl!)
declare -a myarray=( /mydir/tmp*.txt )
array_length=${#myarray[@]}

# Not found if the 1st element of the array is the unexpanded string
# (ie, if it contains a "*")
if [[ ${myarray[0]} =~ [*] ]] ; then
   echo "No files not found"
elif [ $array_length -eq 1 ] ; then
   echo "File was found"
else
   echo "Files were found"
fi

for myfile in ${myarray[@]}
do
  echo "$myfile"
done

Да, это действительно пахнет Perl. Рад, что не вмешался;)

person Ben Slade    schedule 22.02.2018

Я использую это:

filescount=`ls xorg-x11-fonts* | awk 'END { print NR }'`  
if [ $filescount -gt 0 ]; then  
    blah  
fi
person Alexandre Vr.    schedule 21.10.2014
comment
wc -l более эффективен, чем awk для этой задачи. - person dolmen; 24.02.2017
comment
В любом случае подсчет количества результатов - это антипаттерн. Обычно вы просто хотите посмотреть, вернул ли ls успех или нет (а еще лучше избегать ls и использовать встроенные функции оболочки). - person tripleee; 26.09.2017

ИМХО лучше использовать find всегда при тестировании файлов, глобусов или каталогов. Камнем преткновения при этом является статус выхода find: 0, если все пути были пройдены успешно,> 0 в противном случае. Выражение, которое вы передали find, не создает эха в его коде выхода.

В следующем примере проверяется, есть ли в каталоге записи:

$ mkdir A
$ touch A/b
$ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . && echo 'not empty'
not empty

Когда A не имеет файлов, grep завершается ошибкой:

$ rm A/b
$ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . || echo 'empty'
empty

Когда A не существует, grep снова выдает ошибку, потому что find печатает только в stderr:

$ rmdir A
$ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . && echo 'not empty' || echo 'empty'
find: 'A': No such file or directory
empty

Замените -not -empty любым другим find выражением, но будьте осторожны, если -exec команда выводит на стандартный вывод. В таких случаях вы можете найти более конкретное выражение с помощью grep.

Этот подход хорошо работает в сценариях оболочки. Изначально вопрос заключался в поиске шара xorg-x11-fonts*:

if find -maxdepth 0 -name 'xorg-x11-fonts*' -print | head -n1 | grep -q .
then
    : the glob matched
else
    : ...not
fi

Обратите внимание, что ветвление else достигается, если xorg-x11-fonts* не совпало или find обнаружила ошибку. Чтобы отличить регистр, используйте $?.

person Andreas Spindler    schedule 20.03.2016
comment
Вы, вероятно, имели в виду -maxdepth 1 при использовании -name, поскольку -maxdepth 0 будет смотреть на текущий каталог, а не на его содержимое. - person Chris Cogdon; 30.07.2016

Попробуй это

fileTarget="xorg-x11-fonts*"

filesFound=$(ls $fileTarget)  # 2014-04-03 edit 2: removed dbl-qts around $(...)

редактировать 2014-04-03 (удалены двойные кавычки и добавлен тестовый файл Charlie 22.html (2 пробела)

case ${filesFound} in
  "" ) printf "NO files found for target=${fileTarget}\n" ;;
   * ) printf "FileTarget Files found=${filesFound}\n" ;;
esac 

Тест

fileTarget="*.html"  # where I have some html docs in the current dir

FileTarget Files found=Baby21.html
baby22.html
charlie  22.html
charlie21.html
charlie22.html
charlie23.html

fileTarget="xorg-x11-fonts*"

NO files found for target=xorg-x11-fonts*

Обратите внимание, что это работает только в текущем каталоге или где var fileTarget включает путь, который вы хотите проверить.

person shellter    schedule 15.06.2011
comment
Ваш код завершится ошибкой, если fileTarget содержит пробелы (например, fileTarget="my file*"). - person Richard Hansen; 17.06.2011
comment
@RichardHansen, какое решение, когда есть пробелы? - person Ross; 29.03.2014
comment
@Ross: Используйте принятый ответ: if ls "my file"* >/dev/null 2>&1; then ... - person Richard Hansen; 29.03.2014
comment
@RichardHansen, спасибо, извини, у меня не работает. Исправьте это сейчас. - person Ross; 02.04.2014
comment
@Ross, я добавил правку в свою, которая должна работать с файлами с пробелами. В основном case "${filesFound}" in ..... Всем удачи. - person shellter; 02.04.2014
comment
Согласно спецификации POSIX для case, слово после case не подлежит разделению полей или расширению имени пути, поэтому добавленные вами двойные кавычки не действуют. Проблема с разделением полей в ls $fileTarget. - person Richard Hansen; 03.04.2014
comment
@Ross, Ричард Хансен что-то понял, dbl-кавычки на самом деле не имеют значения, может быть, поэтому у меня их вообще не было. Это так давно, я не уверен. Я вернулся в свой тестовый каталог для этого вопроса и сделал ссылку как charlie 22.html, я отредактировал результаты выше. Будет ли это обрабатывать каждый случай так же хорошо, как find ... -print0 | xargs -0 ..?, Возможно, нет. Работает ли он в среде, где вы контролируете, какие имена файлов создаются? Для меня это работает, и я имею в виду, что я использую эту конструкцию регулярно (в среде, где я контролирую создаваемые имена файлов ;-)). Всем удачи. - person shellter; 03.04.2014

Как насчет

if ls -l  | grep -q 'xorg-x11-fonts.*' # grep needs a regex, not a shell glob
then
     # do something
else
     # do something else
fi 
person Ankur Agarwal    schedule 23.06.2017
comment
Нет, не используйте ls в сценариях, а подстановочный знак .* является избыточным (вы, вероятно, имели в виду grep -q '^xorg-x1-fonts'). - person tripleee; 26.09.2017

Если в сетевой папке огромное количество файлов, использование подстановочного знака вызывает сомнения (скорость или переполнение аргументов командной строки).

В итоге я получил:

if [ -n "$(find somedir/that_may_not_exist_yet -maxdepth 1 -name \*.ext -print -quit)" ] ; then
  echo Such file exists
fi
person luxigo    schedule 02.09.2017

Вы также можете вырезать другие файлы

if [ -e $( echo $1 | cut -d" " -f1 ) ] ; then
   ...
fi
person McCloud    schedule 02.10.2017
comment
это будет медленным из-за подоболочки. А что, если в имени файла есть пробел? - person phuclv; 31.05.2018

мужской тест

if [ -e file ]; then
...  
fi

будет работать для dir \ file.

С уважением

person Shokodemon    schedule 16.04.2013
comment
Это не будет работать с подстановочными знаками (что и задается в этом вопросе). Если он соответствует более чем одному файлу, вы получите bash: [: too many arguments - person user000001; 17.04.2013
comment
Немного несправедливо, так как это очень хорошо работает на Solaris ........ - person SnazzyBootMan; 09.10.2015
comment
хех, старый пост, спасибо за поддержку Крис - я действительно работал с Solaris тогда. - person Shokodemon; 24.09.2017

person    schedule
comment
Это похоже на сумку с антипаттернами «не делай этого». Не используйте ls в скриптах, не проверяйте, равно ли нулю количество слов, следите за логикой кренделя с обратными кавычками. - person tripleee; 31.07.2020