Как узнать, существует ли обычный файл в Bash?
я использовал следующий скрипт, чтобы узнать, существует ли файл:
#!/bin/bash
FILE=
if [ -f $FILE ]; then
echo "File $FILE exists."
else
echo "File $FILE does not exist."
fi
какой правильный синтаксис использовать, если я хочу только проверить, делает ли файл не?
#!/bin/bash
FILE=
if [ $FILE does not exist ]; then
echo "File $FILE does not exist."
fi
17 ответов
Тестирование Файлов Bash
-b filename
- специальный блочный файл-c filename
- специальный символьный файл-d directoryname
- проверьте наличие каталога-e filename
- проверка на существование файла, независимо от типа (узел, каталог, розетки и т. д.)-f filename
- проверьте наличие обычного файла, а не каталога-G filename
- проверьте, существует ли файл и принадлежит эффективной группе ID-G filename set-group-id
- True, если файл существует и set-group-id-k filename
- липкий бит-L filename
- символическая ссылка-O filename
- True, если файл существует и принадлежит эффективному id пользователя-r filename
- проверьте, является ли файл читаемым-S filename
- проверьте, является ли файл socket-s filename
- проверьте, если файл имеет ненулевой размер-u filename
- проверьте, установлен ли бит file set-user-id-w filename
- Проверьте, доступен ли файл для записи-x filename
- проверьте, является ли файл исполняемым
как использовать:
#!/bin/bash
file=./file
if [ -e "$file" ]; then
echo "File exists"
else
echo "File does not exist"
fi
A тест выражение можно отрицать с помощью !
оператор
#!/bin/bash
file=./file
if [ ! -e "$file" ]; then
echo "File does not exist"
else
echo "File exists"
fi
вы можете отрицать выражение с помощью "!":
#!/bin/bash
FILE=
if [ ! -f "$FILE" ]
then
echo "File $FILE does not exist"
fi
соответствующие man-страницы man test
или, что эквивалентно, man [
-- или help test
или help [
для встроенной команды bash.
[[ -f $FILE ]] || printf '%s does not exist!\n' "$FILE"
кроме того, возможно, что файл является сломанной символической ссылкой или нерегулярным файлом, например, сокетом, устройством или fifo. Например, чтобы добавить чек на сломанные символические ссылки:
if [[ ! -f $FILE ]]; then
if [[ -L $FILE ]]; then
printf '%s is a broken symlink!\n' "$FILE"
else
printf '%s does not exist!\n' "$FILE"
fi
fi
стоит отметить, что если вам нужно выполнить одну команду можно сократить
if [ ! -f "$file" ]; then
echo "$file"
fi
to
test -f "$file" || echo "$file"
или
[ -f "$file" ] || echo "$file"
Я предпочитаю делать следующий однострочный, в POSIX shell совместимый формат:
$ [ -f "/$DIR/$FILE" ] || echo "$FILE NOT FOUND"
$ [ -f "/$DIR/$FILE" ] && echo "$FILE FOUND"
для нескольких команд, как я бы сделал в скрипте:
$ [ -f "/$DIR/$FILE" ] || { echo "$FILE NOT FOUND" ; exit 1 ;}
Как только я начал это делать,я редко использую полностью типизированный синтаксис!!
чтобы проверить существование файла, параметр может быть одним из следующих:
-e: Returns true if file exists (regular file, directory, or symlink)
-f: Returns true if file exists and is a regular file
-d: Returns true if file exists and is a directory
-h: Returns true if file exists and is a symlink
все тесты ниже применяются к обычным файлам, каталогам и символическим ссылкам:
-r: Returns true if file exists and is readable
-w: Returns true if file exists and is writable
-x: Returns true if file exists and is executable
-s: Returns true if file exists and has a size > 0
пример:
#!/bin/bash
FILE=
if [ -f "$FILE" ]; then
echo "File $FILE exists"
else
echo "File $FILE does not exist"
fi
вы должны быть осторожны при запуске test
для некотируемой переменной, поскольку это может привести к неожиданным результатам:
$ [ -f ]
$ echo $?
0
$ [ -f "" ]
$ echo $?
1
рекомендация обычно состоит в том, чтобы тестируемая переменная была окружена двойными кавычками:
#!/bin/sh
FILE=
if [ ! -f "$FILE" ]
then
echo "File $FILE does not exist."
fi
существуют три различных способа сделать это:
-
отрицание статуса выхода с bash (ни один другой ответ не сказал этого):
if ! [ -e "$file" ]; then echo "file does not exist" fi
или:
! [ -e "$file" ] && echo "file does not exist"
-
отрицание теста внутри команды test
[
(именно так большинство ответов до этого представили):if [ ! -e "$file" ]; then echo "file does not exist" fi
или:
[ ! -e "$file" ] && echo "file does not exist"
-
действуйте на результат отрицательного теста (
||
вместо&&
):только:
[ -e "$file" ] || echo "file does not exist"
это выглядит глупо (IMO), не используйте его, если ваш код не должен быть переносным в оболочку Bourne (например,
/bin/sh
Solaris 10 или более ранних версий), которому не хватало оператора отрицания трубопровода (!
):if [ -e "$file" ]; then : else echo "file does not exist" fi
вы можете сделать это:
[[ ! -f "$FILE" ]] && echo "File doesn't exist"
или
if [[ ! -f "$FILE" ]]; then
echo "File doesn't exist"
fi
если вы хотите проверить файл и папку, а затем использовать вместо -f
. -e
возвращает true для обычных файлов, каталогов, сокетов, специальных файлов символов, специальных файлов блоков и т. д.
на
[ -f "$file" ]
the тут stat()
(не lstat()
) системный вызов по пути, хранящемуся в $file
и возвращает правда если этот системный вызов выполняется успешно и тип файла, возвращаемого stat()
- это "регулярные".
если [ -f "$file" ]
возвращает true, вы можете сказать, файл существует и является обычным файлом или символической ссылкой, в конечном итоге, решать в обычный файл (или по крайней мере это было на момент stat()
).
[ ! -f "$file" ]
или ! [ -f "$file" ]
return true), есть много различных возможностей:
- файл не существует
- файл существует, но не является обычным файлом
- файл существует, но у вас нет разрешения на поиск в Родительском каталоге
- файл существует, но этот путь для доступа к нему слишком длинный
- файл является символической ссылкой на обычный файл, но у вас нет разрешения на поиск для некоторых каталогов, участвующих в разрешении символической ссылки.
- ... любая другая причина, почему
stat()
системный вызов может завершиться неудачей.
короче говоря, это должно быть:
if [ -f "$file" ]; then
printf '"%s" is a path to a regular file or symlink to regular file\n' "$file"
elif [ -e "$file" ]; then
printf '"%s" exists but is not a regular file\n' "$file"
elif [ -L "$file" ]; then
printf '"%s" exists, is a symlink but I cannot tell if it eventually resolves to an actual file, regular or not\n' "$file"
else
printf 'I cannot tell if "%s" exists, let alone whether it is a regular file or not\n' "$file"
fi
чтобы знать наверняка, что файл не существует, нам понадобится stat()
системный вызов для возврата с кодом ошибки ENOENT
(ENOTDIR
говорит нам, что один из компонентов пути не является каталогом, это еще один случай, когда мы можем сказать, что файл не существует по этому пути). К сожалению,[
команда не дает нам знать об этом. Он вернет false, является ли код ошибки ENOENT, EACCESS (разрешение отказано), ENAMETOOLONG или что-либо еще.
на [ -e "$file" ]
тест также можно сделать с ls -Ld -- "$file" > /dev/null
. В таком случае ...--20--> скажет вам, почему stat()
не удалось, хотя информация может быть легко использована программно:
$ file=/var/spool/cron/crontabs/root
$ if [ ! -e "$file" ]; then echo does not exist; fi
does not exist
$ if ! ls -Ld -- "$file" > /dev/null; then echo stat failed; fi
ls: cannot access '/var/spool/cron/crontabs/root': Permission denied
stat failed
по крайней мере ls
говорит мне, что это не потому, что файл не существует, что он терпит неудачу. Потому что он не может сказать, существует файл или нет. The [
команда просто проигнорировала проблему.
С zsh
shell, вы можете запросить код ошибки с помощью $ERRNO
специальная переменная после сбоя [
команда и декодировать это число с помощью $errnos
специальный массив в zsh/system
модуль:
zmodload zsh/system
ERRNO=0
if [ ! -f "$file" ]; then
err=$ERRNO
case $errnos[err] in
("") echo exists, not a regular file;;
(ENOENT|ENOTDIR)
if [ -L "$file" ]; then
echo broken link
else
echo does not exist
fi;;
(*) echo "can't tell"; syserror "$err"
esac
fi
(остерегайтесь $errnos
поддерживает несколько версий zsh
при построении с последними версиями gcc
).
чтобы отменить тест, используйте "!". Это эквивалентно логическому оператору" не " на других языках. Попробуйте это:
if [ ! -f /tmp/foo.txt ];
then
echo "File not found!"
fi
или написано немного по-другому:
if [ ! -f /tmp/foo.txt ]
then echo "File not found!"
fi
или вы можете использовать:
if ! [ -f /tmp/foo.txt ]
then echo "File not found!"
fi
или, пресинг все вместе:
if ! [ -f /tmp/foo.txt ]; then echo "File not found!"; fi
который может быть записан (используя тогда "и" оператор:&&) как:
[ ! -f /tmp/foo.txt ] && echo "File not found!"
, который выглядит короче такой:
[ -f /tmp/foo.txt ] || echo "File not found!"
на test
что может рассчитывать. Это сработало для меня (на основе Bash Shell: проверить файл существует или нет):
test -e FILENAME && echo "File exists" || echo "File doesn't exist"
этот код также работает .
#!/bin/bash
FILE=
if [ -f $FILE ]; then
echo "File '$FILE' Exists"
else
echo "The File '$FILE' Does Not Exist"
fi
этот сценарий оболочки также работает для поиска файла в каталоге:
echo "enter file"
read -r a
if [ -s /home/trainee02/"$a" ]
then
echo "yes. file is there."
else
echo "sorry. file is not there."
fi
иногда может быть удобно использовать & & и / / операторы.
как в (если у вас есть команда "test"):
test -b $FILE && echo File not there!
или
test -b $FILE || echo File there!