Я пытаюсь написать if
заявление, чтобы проверить, есть ли какие-либо файлы, соответствующие определенному шаблону. Если в каталоге есть текстовый файл, он должен запустить данный скрипт.
Мой код в настоящее время:
if [ -f /*.txt ]; then ./script fi
Пожалуйста, дайте несколько идей; Я хочу запустить скрипт, только если .txt
в каталоге есть.
shell-script
files
wildcards
test
user40952
источник
источник
/
? Кроме того, вы пропустите точку с запятой раньшеfi
.find
как описано здесь , на StackOverflow .Ответы:
вернет true, только если есть один (и только один) не скрытый файл, в
/
имени которого заканчивается имя,.txt
и если этот файл является обычным файлом или символической ссылкой на обычный файл.Это связано с тем, что подстановочные знаки раскрываются оболочкой перед передачей в команду (здесь
[
).Так что, если есть
/a.txt
и/b.txt
,[
будут переданы 5 аргументов:[
,-f
,/a.txt
,/b.txt
и]
.[
потом жаловался бы, что-f
дано слишком много аргументов.Если вы хотите убедиться, что
*.txt
шаблон расширяется хотя бы до одного скрытого файла (обычного или нет):shopt -s nullglob
являетсяbash
конкретным, но скорлупа нравитсяksh93
,zsh
,yash
,tcsh
имеют эквивалентные высказывания.Обратите внимание, что он находит эти файлы, читая содержимое каталога, он вообще не пытается получить доступ к этим файлам, что делает его более эффективным, чем решения, которые вызывают такие команды, как
ls
илиstat
в этом списке файлов, вычисляемых оболочкой.Стандартный
sh
эквивалент будет:Проблема в том, что с оболочками Bourne или POSIX, если шаблон не совпадает, он расширяется до самого себя. Так что, если
*.txt
расширится до*.txt
, вы не знаете, будет ли это потому, что в.txt
каталоге нет файла или потому что есть один названный файл*.txt
. Использование[*].txt *.txt
позволяет различать два.источник
[ -f /*.txt ]
довольно быстро по сравнению сcompgen
.[ -f /*.txt ]
был бы неправильным, но в моем тесте для каталога, содержащего3425
файлы,94
которые не являются скрытыми текстовыми файлами,compgen -G "*.txt" > /dev/null 2>&1
скорость оказалась равнойset -- *.txt; [ "$#" -gt 0 ]
(20,5 секунд для обоих при повторении 10000 раз в моем случае).Вы всегда можете использовать
find
:Объяснение:
find .
: поиск в текущем каталоге-maxdepth 1
: не искать подкаталоги-type f
: поиск только обычных файловname "*.txt"
: поиск файлов, оканчивающихся на.txt
2>/dev/null
: перенаправить сообщения об ошибках в/dev/null
| grep -q .
: grep для любого символа, вернет false, если символы не найдены.&& ./script
: Выполнить,./script
только если предыдущая команда была успешной (&&
)источник
find
возвращает false только в том случае, если у него возникают проблемы с поиском файлов, но не в том случае, если файл не найден Вы хотите передать вывод,grep -q .
чтобы проверить, если он что-то находит.chmod a-x .
.Возможное решение также встроено в Bash
compgen
. Эта команда возвращает все возможные совпадения для шаблона выделения и имеет код выхода, указывающий, совпадают ли какие-либо файлы.Я нашел этот вопрос, когда искал решения, которые быстрее.
источник
LC_ALL=C compgen -G "*.txt" > /dev/null
.Вот один лайнер, чтобы сделать это:
файлы существуют
файлы не существуют
Этот подход использует
||
и&&
оператор в Баше. Это операторы «или» и «и».Таким образом, если команда stat возвращает значение,
$?
равное 0,echo
вызывается первая , если возвращается 1, тоecho
вызывается вторая .вернуть результаты из статистики
Этот вопрос подробно рассматривается на стековом потоке:
источник
stat
когдаls -d
можно сделать то же самое?ls -d
списки каталог? Кажется, не работает, когда я просто попытался перечислить каталог с файлами,ls -d *.pl
например, в нем.&&
,ls *.txt
и оно также будет работать. Убедитесь, что вы отправили stdout и stderr в/dev/null
соответствии с рекомендациями @slm.ls *.txt
и нет никаких файлов присутствуют в каталоге это будет возвращать$? = 2
, который все равно будет работать с , если тогда, но это был один из моих причин для выбораstat
болееls
. Я хотел 0 для успеха и 1 для неудачи.ls -d
это список каталогов вместо их содержимого. Такls -d
что просто делаетlstat
на файл, как GNUstat
делает. То, что ненулевые команды статуса выхода возвращаются при сбое, зависит от системы, поэтому нет смысла делать на них предположения.Как указывает Chazelas, ваш скрипт потерпит неудачу, если расширение по шаблону соответствует более чем одному файлу.
Тем не менее, есть хитрость, которую я использую ( даже если она мне не очень нравится ):
Как это работает?
Расширение с подстановочными знаками будет соответствовать массиву имен файлов, мы получим первое, если они есть, в противном случае - null, если совпадения нет.
источник
.txt
файлов, которые являются обычными . Попробуйте, например, послеmkdir a.txt; mkfifo b.txt; echo regular > c.txt
.Просто как:
wc -l
считает строки в расширенном шаблоне.источник
ls
вывод и почти никогда не проверять$?
напрямую, потому что этоif
уже сделано. Кроме того, использование,wc
чтобы увидеть, произошло ли что-то подобное, неправильно направлено.Мне нравится предыдущее решение с массивами, но оно может стать расточительным при большом количестве файлов - оболочка будет использовать много памяти для построения массива, и будет проверен только первый элемент.
Вот альтернативная структура, которую я тестировал вчера:
$ cd /etc; if [[ $(echo * | grep passwd) ]];then echo yes;else echo no;fi yes $ cd /etc; if [[ $(echo * | grep password) ]];then echo yes;else echo no;fi no
Значение выхода из grep, по-видимому, определяет путь через управляющую структуру. Это также тестирует с регулярными выражениями, а не с шаблонами оболочки. Некоторые из моих систем имеют команду «pcregrep», которая позволяет выполнять более сложные сопоставления регулярных выражений.
(Я отредактировал этот ответ, чтобы убрать «ls» в подстановке команд после прочтения вышеупомянутой критики за ее анализ.)
источник
если вы хотите использовать предложение if, оцените количество:
источник