Как бы вы сказали, присутствуют ли файлы с определенным расширением в каталоге с помощью bash?
Что-то вроде
if [ -e *.flac ]; then
echo true;
fi
Ответы:
#!/bin/bash
count=`ls -1 *.flac 2>/dev/null | wc -l`
if [ $count != 0 ]
then
echo true
fi
ls -l
, мой ответ используетls -1
ls -1
он будет печатать одну строку для каждого файла
\n
(и да, это действительно в именах файлов).
#/bin/bash
myarray=(`find ./ -maxdepth 1 -name "*.py"`)
if [ ${#myarray[@]} -gt 0 ]; then
echo true
else
echo false
fi
${#myarray[@]}
равный 1
ls -1 *.py
вместо find
При этом используется ls (1), если файлов flac не существует, ls сообщает об ошибке, и сценарий завершается; в противном случае сценарий продолжается, и файлы могут быть обработаны
#! /bin/sh
ls *.flac >/dev/null || exit
## Do something with flac files here
if ls *.flac >/dev/null 2>&1; then ... fi;
shopt -s nullglob
if [[ -n $(echo *.flac) ]] # or [ -n "$(echo *.flac)" ]
then
echo true
fi
Вы должны быть осторожны, какой флаг вы добавляете в свое if
утверждение и как он соотносится с желаемым результатом.
Если вы хотите проверять только обычные файлы, а не другие типы записей файловой системы, вам нужно изменить скелет кода на:
if [ -f file ]; then
echo true;
fi
Использование -f
ограничивается if
обычными файлами, тогда как -e
оно более обширное и соответствует всем типам записей файловой системы. Конечно, есть и другие варианты, такие как -d
каталоги и т. Д. См. Http://tldp.org/LDP/abs/html/fto.html для хорошего списка.
Как указано в @msw, test
(т.е. [
) задохнется, если вы попытаетесь передать ему более одного аргумента. Это может произойти в вашем случае, если glob for *.flac
вернул более одного файла. В этом случае попробуйте обернуть if
тест в цикл, например:
for file in ./*.pdf
do
if [ -f "${file}" ]; then
echo 'true';
break
fi
done
Таким образом, вы выберете break
первый экземпляр нужного вам расширения файла и сможете продолжить работу с остальной частью скрипта.
test
(aka [
) жалуется, если шаблон расширяется до более чем одного файла: «ожидается бинарный оператор» или «слишком много аргументов»
"$file"
, потому что имя файла может содержать некоторые неправильные символы, такие как пробелы или звездочки.
Лучшее решение (if [ -e *.flac ];)
не сработало для меня, дав:[: too many arguments
if ls *.flac >/dev/null 2>&1;
тогда это будет работать.
Вы можете использовать -f, чтобы проверить, существуют ли файлы определенного типа:
#!/bin/bash
if [ -f *.flac ] ; then
echo true
fi
[
(в отличие от более распространенной [[
) не предотвращает подстановку.
shopt -s nullglob
set -- $(echo *.ext)
if [ "${#}" -gt 0 ];then
echo "got file"
fi
-ge
вместо -gt
, потому что иначе ваш код не обнаружит один файл. Во-вторых, если нет файлов, соответствующих шаблону, любая соответствующая оболочка оставит строку *.ext
нетронутой, так что вы все равно получите один «результат».
только bash:
any_with_ext () (
ext="$1"
any=false
shopt -s nullglob
for f in *."$ext"; do
any=true
break
done
echo $any
)
if $( any_with_ext flac ); then
echo "have some flac"
else
echo "dir is flac-free"
fi
Я использую круглые скобки вместо фигурных скобок, чтобы гарантировать, что используется подоболочка (не хочу, чтобы ваши текущие nullglob
настройки были искажены ).
Вот решение, в котором не используются внешние команды (т.е. нет ls
), а вместо этого используется функция оболочки. Протестировано в bash:
shopt -s nullglob
function have_any() {
[ $# -gt 0 ]
}
if have_any ./*.flac; then
echo true
fi
Функция have_any
использует $#
для подсчета своих аргументов, а [ $# -gt 0 ]
затем проверяет, есть ли хотя бы один аргумент. Использование ./*.flac
вместо вместо простого *.flac
вызова to have_any
позволяет избежать проблем, вызванных файлами с такими именами, как --help
.
Для завершения с помощью zsh:
if [[ -n *.flac(#qN) ]]; then
echo true
fi
Это указано в конце раздела « Условные выражения » в руководстве по zsh. Поскольку [[
отключает подстановку имени файла, нам нужно принудительно генерировать имя файла, используя (#q)
в конце строки подстановки, затем N
флаг ( NULL_GLOB
параметр), чтобы сгенерированная строка была пустой в случае отсутствия совпадения.
Вот довольно простое решение:
if [ "$(ls -A | grep -i \\.flac\$)" ]; then echo true; fi
Как видите, это всего лишь одна строка кода, но она работает достаточно хорошо. Он должен работать как с bash, так и с posix-совместимой оболочкой, такой как dash. Он также нечувствителен к регистру и не заботится о том, какие типы файлов (обычные, символические ссылки, каталоги и т. Д.) Присутствуют, что может быть полезно, если у вас есть некоторые символические ссылки или что-то в этом роде.
Я пробовал это:
if [ -f *.html ]; then
echo "html files exist"
else
echo "html files dont exist"
fi
Я без проблем использовал этот фрагмент кода для других файлов, но для файлов html получил ошибку :
[: too many arguments
Затем я попробовал решение подсчета @ JeremyWeir, которое сработало для меня.
Имейте в виду, что вам придется сбросить счетчик, если вы делаете это в цикле:
count=$((0))
Это должно работать в любой подобной оболочке:
if [ "$(find . -maxdepth 1 -type f | grep -i '.*\.flac$')" ]; then
echo true
fi
Это также работает с GNU find
, но IDK, если он совместим с другими реализациями find
:
if [ "$(find . -maxdepth 1 -type f -iname \*.flac)" ]; then
echo true
fi