Як би ви розповіли, чи є файли певного розширення в каталозі за допомогою 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замість пошуку
Тут використовується 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 для *.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недоторканим, тому ви все одно отримаєте один "результат".
лише баш:
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у виклику 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, як тире. Він також не враховує регістр, і йому байдуже, який тип файлів (звичайний, символьне посилання, каталог тощо) присутній, що може бути корисним, якщо у вас є якісь посилання чи щось інше.
Я спробував це:
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