Команда для отображения произвольного сообщения, если существует определенный файл


11

Есть ли команда для отображения сообщения «Да», если конкретный файл существует? Не нужно давать функциональность, если файл не существует.

Ответы:


25

Используйте эту простую однострочную версию Bash:

if [ -e FILENAME ] ; then echo Yes ; fi

Не В -eконтрольных истинен , если FILENAMEсуществует, то, независимо от того , что он (файл, каталог, ссылки, устройство, ...).

Если вы хотите проверять только обычные файлы, используйте -fвместо этого, как сказал @Arronical .


18
[ -e FILENAME ] && echo Yes
Зеб МакКоркл

@ZebMcCorkle Правильно, это тоже работает. Вы можете опубликовать это как отдельный ответ.
Byte Commander

3
Если FILENAMEрасширение является переменным или содержит какие-либо специальные символы, не забудьте указать его в кавычках. например, в сценарии [ -e "$1" ] && echo Yes.
Питер Кордес

@PeterCordes если вы используете Баш вы можете использовать [[и ]]вместо того, чтобы цитировать переменную.
Holloway

1
@Holloway: да, но иногда вам нужно написать переносимые скрипты, которые требуют только POSIX sh. Вот почему я дал безопасную версию этого, вместо того, чтобы понизить голосование и отменить ответ bash. Также обратите внимание, что не является проблемой заключать в кавычки расширения внутри [[ ]], всегда цитирование - хорошая привычка для начинающих, которые не помнят специальных правил для внутри [[ ]]оператора или для арифметического контекста.
Питер Кордес

10

Вы можете использовать этот простой скрипт:

#!/bin/bash

if [[ -f $1 ]]; then
    echo "Yes"
    exit 0
else
    exit 1
fi

Сохранить как file-exists.sh. Затем в Терминале введите chmod +x file-exists.sh.

Используйте его так: ./file-exists.sh FILEгде вы заменяете FILEфайлом, который хотите проверить, например:

./file-exists.sh file.txt

Если file.txtсуществует, Yesбудет распечатан в Терминал, и программа выйдет со статусом 0 (успех). Если файл не существует, ничего не будет напечатано, и программа выйдет со статусом 1 (ошибка).

Если вам интересно, почему я включил exitкоманду, читайте дальше ...


Что случилось с exitкомандой?

exitвызывает нормальное завершение процесса. По сути, это означает: он останавливает сценарий. Он принимает необязательный (числовой) параметр, который будет состоянием завершения скрипта, который его вызвал.

Этот статус выхода позволяет другим сценариям использовать ваш file-existsсценарий и позволяет узнать, существует файл или нет.

Простой пример использования этого скрипта (сохраните как file-exists-cli.sh):

#!/bin/bash

echo "Enter a filename and I will tell you if it exists or not: "
read FILE
# Run `file-exists.sh` but discard any output because we don't need it in this example
./file-exists.sh $FILE &>> /dev/null
# #? is a special variable that holds the exit status of the previous command
if [[ $? == 0 ]]; then
    echo "$FILE exists"
else
    echo "$FILE does not exist"
fi

Сделай как обычно chmod +x file-exists-cli.shи потом запусти ./file-exists-cli.sh. Вы увидите что-то вроде этого:

Файл существует ( exit 0):

➜  ~ ./file-exists-cli.sh 
Enter a filename and I will tell you if it exists or not: 
booleans.py
booleans.py exists

Файл не существует ( exit 1):

➜  ~ ./file-exists-cli.sh
Enter a filename and I will tell you if it exists or not: 
asdf
asdf does not exist

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

9

В оболочке bash в командной строке.

if [[ -f /path/to/file ]]; then echo "Yes"; fi

Он использует условный оператор bash -fи проверяет, существует ли файл и является ли он обычным файлом. Если вы хотите проверить какие-либо файлы, включая каталоги и ссылки, используйте -e.

Это отличный ресурс для условных выражений bash.


1
Почему двойные скобки?
Byte Commander

1
Я не фанат testоригинального формата, я знаю, что это излишне, но это моя привычка.
Arronical

7
@ByteCommander: двойные скобки, как правило, лучше, чем одиночные. Они являются частью синтаксиса оболочки (вместо того, чтобы вызывать [команду, которая обычно вызывает встроенную функцию). Они исправляют несоответствия и тупое поведение одной версии скобки. [Встроенный модуль остается совместимым, но я не вижу веской причины использовать его в новом коде bash. (Если вам нужно написать POSIX-совместимые сценарии, которые могут работать на древних оболочках или что-то в этом роде, это другое дело.)
Ник Маттео

@kundor: По большому счету согласен, что, честно говоря, « [обычно называет встроенным» сомнительно. type -a [для меня перечисляет "встроенная оболочка", затем " /usr/bin/[."
wchargin

1
@wchargin: Боюсь, я не понимаю, к чему ты клонишь. Ваши typeрезультаты, кажется, подтверждают то, что я сказал, нет?
Ник Маттео

5

Самая короткая команда для выполнения того, что вы хотите:

test -e FILENAME && echo Yes

test -eпроверит, существует ли данное имя в файловой системе. (Вы можете использовать test -fтолько обычные файлы. См. Подробнее man test.)

Если данное условие оценивается как истинное, testвозвращается статус успешного завершения (в противном случае возвращается статус ошибки). Мы объединяем две команды, используя &&, что означает «выполнить следующую команду, если предыдущая команда вышла со статусом успеха». Следующая команда просто печатает Yesна стандартном выводе; в случае интерактивной оболочки на терминале.

Это позволяет избежать дополнительного текстового материала ifутверждения, но дает тот же результат. Использование &&(или его противоположность ||) для объединения команд работает хорошо, когда задействована только одна команда. Если вы хотите сделать больше, чем просто выполнить одну команду в ответ на состояние выхода одной команды, то использование ifсинтаксиса быстро станет намного более читабельным.

Как уже указывалось в других ответах, эквивалентная ifстилевая конструкция будет:

if test -e FILENAME; then echo Yes; fi

или альтернативно:

if test -e FILENAME
then
    echo Yes
fi

Для этих целей [и testявляются эквивалентными, за исключением того, что [требует прекращения ].


4

Чтобы снять этот тип вопроса, есть несколько способов, и вот еще один: используйте findкоманду с -execфлагом. Путь к файлу можно разделить на две части, find /etcкоторые задают каталог и в -name FILENAMEкотором указано имя файла (duh!). -maxdepthбудет продолжать findработать /etcтолько с каталогом и не будет переходить в подкаталоги

adminx@L455D:~$ find /etc -maxdepth 1  -name passwd -exec printf "YES\n" \;
YES
adminx@L455D:~$ find /etc -maxdepth 1  -name passwd1 -exec printf "YES\n" \;
adminx@L455D:~$ 

Другой способ, через stat:

adminx@L455D:~$ stat /etc/passwd1 &>/dev/null && echo YES
adminx@L455D:~$ stat /etc/passwd &>/dev/null && echo YES
YES

И альтернативно через питон:

>>> import os
>>> if os.stat('/etc/passwd'): 
...    print 'YES'
... 
YES
>>> if os.stat('/etc/passwd1'): 
...    print 'YES'
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 2] No such file or directory: '/etc/passwd1'

Или короткая альтернатива командной строки:

 python -c "from os.path import exists; print 'Yes' if exists('/etc/fstab') else '' "
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.