Как узнать, существует ли обычный файл в Bash?

Я использовал следующий script, чтобы увидеть, существует ли файл:

#!/bin/bash

FILE=$1     
if [ -f $FILE ]; then
   echo "File $FILE exists."
else
   echo "File $FILE does not exist."
fi

Какой правильный синтаксис использовать, если я только хочу проверить, существует ли файл не?

#!/bin/bash

FILE=$1     
if [ $FILE does not exist ]; then
   echo "File $FILE does not exist."
fi

Ответ 1

Команда test ([ здесь) имеет "не" логический оператор, который является восклицательным знаком (подобно многим другим языки). Попробуйте следующее:

if [ ! -f /tmp/foo.txt ]; then
    echo "File not found!"
fi

Ответ 2

Bash Тестирование файлов

-b filename - Заблокировать специальный файл
-c filename - Файл специального символа
-d directoryname - Проверить каталог Существование
-e filename - Проверить наличие файла, независимо от типа (node, directory, socket и т.д.)
-f filename - Проверить наличие обычного файла, а не каталог
-G filename - Проверьте, существует ли файл и принадлежит ли он эффективному идентификатору группы

-G filename set-group-id - Истина, если файл существует и задан как set-group-id
-k filename - Липкий бит
-L filename - Символическая ссылка
-O filename - Истина, если файл существует и принадлежит эффективному идентификатору пользователя
-r filename - Проверьте, является ли файл доступным для чтения -S filename - Проверьте, является ли файл socket -S filename - Проверьте, не является ли файл ненулевым размером
-u filename - Проверьте, установлен ли бит файла 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 

Тестовое выражение можно отрицать с помощью оператора !

#!/bin/bash
file=./file
if [ ! -e "$file" ]; then
    echo "File does not exist"
else 
    echo "File exists"
fi 

Ответ 3

Вы можете отменить выражение с помощью "!":

#!/bin/bash
FILE=$1

if [ ! -f "$FILE" ]
then
    echo "File $FILE does not exist"
fi

Соответствующая справочная страница man test или, эквивалентно, man [ - или help test или help [ для встроенной команды bash.

Ответ 4

[[ -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

Ответ 5

Стоит отметить, что если вам нужно выполнить одну команду, вы можете сокращать

if [ ! -f "$file" ]; then
    echo "$file"
fi

к

test -f "$file" || echo "$file"

или

[ -f "$file" ] || echo "$file"

Ответ 6

Я предпочитаю делать следующий однострочный шрифт в POSIX формате, совместимом с оболочкой:

$ [ -f "/$DIR/$FILE" ] || echo "$FILE NOT FOUND"

$ [ -f "/$DIR/$FILE" ] && echo "$FILE FOUND"

Для нескольких команд, как я бы сделал в script:

$  [ -f "/$DIR/$FILE" ] || { echo "$FILE NOT FOUND" ; exit 1 ;}

Как только я начал делать это, я редко использую полностью типизированный синтаксис больше!

Ответ 7

Чтобы проверить существование файла, параметр может быть любым из следующих:

-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

Пример script:

#!/bin/bash
FILE=$1

if [ -f "$FILE" ]; then
   echo "File $FILE exists"
else
   echo "File $FILE does not exist"
fi

Ответ 8

Вы можете сделать это:

[[ ! -f "$FILE" ]] && echo "File doesn't exist"

или же

if [[ ! -f "$FILE" ]]; then
    echo "File doesn't exist"
fi

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

Ответ 9

Вы должны быть осторожны при запуске test для некотируемой переменной, поскольку это может привести к неожиданным результатам:

$ [ -f ]
$ echo $?
0
$ [ -f "" ]
$ echo $?
1

Обычно рекомендуется, чтобы тестируемая переменная была окружена двойными кавычками:

#!/bin/sh
FILE=$1

if [ ! -f "$FILE" ]
then
   echo "File $FILE does not exist."
fi

Ответ 10

Существует три различных способа сделать это:

  • Отмените статус выхода с помощью bash (ни один другой ответ не сказал об этом):

    if ! [ -e "$file" ]; then
        echo "file does not exist"
    fi
    

    Или:

    ! [ -e "$file" ] && echo "file does not exist"
    
  • Отмените тест внутри тестовой команды [ (таким образом, как большинство ответов до этого было представлено):

    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
    

Ответ 11

В

[ -f "$file" ]

[ команда выполняет системный вызов stat() (не lstat()) для пути, хранящегося в $file и возвращает true, если этот системный вызов завершился успешно, а тип файла, возвращаемый stat() является "обычным".

Поэтому, если [ -f "$file" ] возвращает true, вы можете сказать, что файл существует и является обычным файлом или символической ссылкой, в конечном итоге преобразующейся в обычный файл (или, по крайней мере, это было во время использования stat()).,

Однако, если он возвращает false (или если [ ! -f "$file" ] или ! [ -f "$file" ] возвращает true), существует много разных возможностей:

  • файл не существует
  • файл существует, но не является обычным файлом (это может быть устройство, fifo, каталог, сокет...)
  • файл существует, но у вас нет разрешения на поиск в родительском каталоге
  • файл существует, но путь к нему слишком длинный
  • файл является символической ссылкой на обычный файл, но у вас нет разрешения на поиск в некоторых каталогах, участвующих в разрешении символической ссылки.
  • ... любая другая причина, по которой системный вызов 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. В этом случае ls скажет вам, почему 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 говорит мне это не потому, что файл не существует, потому что он не работает. Это потому, что он не может сказать, существует файл или нет. Команда [ просто проигнорировала проблему.

В оболочке zsh вы можете запросить код ошибки с помощью специальной переменной $ERRNO после неудачной команды [ и декодировать это число с $errnos специального массива $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;;
    (*) syserror -p "can't tell: " "$err"
  esac
fi

( $errnos поддержка $errnos была нарушена в некоторых версиях zsh при $errnos с последними версиями gcc).

Ответ 12

Чтобы отменить тест, используйте "!". Это эквивалентно "не" логическому оператору на других языках. Попробуйте следующее:

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!"

Ответ 13

Этот код также работает.

#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
 echo "File '$FILE' Exists"
else
 echo "The File '$FILE' Does Not Exist"
fi

Ответ 15

Самый простой способ

FILE=$1
[ ! -e "${FILE}" ] && echo "does not exist" || echo "exists"

Ответ 16

Эта оболочка script также работает для поиска файла в каталоге:

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

Ответ 17

иногда бывает удобно использовать && и || операторы.

Как и в (если у вас есть команда "test" ):

test -b $FILE && echo File not there!

или

test -b $FILE || echo File there!

Ответ 18

Если вы хотите использовать test вместо [], то вы можете использовать !, чтобы получить отрицание:

if ! test "$FILE"; then
  echo "does not exist"
fi

Ответ 19

Вы также можете сгруппировать несколько команд в один вкладыш

[ -f "filename" ] || ( echo test1 && echo test2 && echo test3 )

или же

[ -f "filename" ] || { echo test1 && echo test2 && echo test3 ;}

Если имя файла не выходит, вывод будет

test1
test2
test3

Примечание: (...) работает в подоболочке, {...;} работает в той же оболочке. Запись в фигурных скобках работает только в bash.