файлов - проверить папку на существование bash




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

В

[ -f "$file" ]

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

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

Однако, если он возвращает false (или если [ ! -f "$file" ] или ! [ -f "$file" ] возвращает 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 . В этом случае 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 после команды failing [ command и декодировать этот номер, используя специальный массив $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 ).

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

#!/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

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

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

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

#!/bin/sh
FILE=$1

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

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

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

или же

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

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


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

-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=$1

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

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

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

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

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

в

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

или же

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

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

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

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

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

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

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

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

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

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

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


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

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

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

или же

test -b $FILE || echo File there!

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

-b filename - заблокировать специальный файл
-c filename - Специальный файл символов
-d directoryname - Проверить каталог
-e filename - проверить наличие файла, независимо от типа (узла, каталога, сокета и т. д.).
-f filename - Проверить наличие обычного файла, а не каталог
-G filename - проверить, существует ли файл и принадлежит ли его действительный идентификатор группы
-G filename set-group-id - True, если файл существует и имеет значение set-group-id
-k filename - Sticky bit
-L filename - Символическая ссылка
-O filename - True, если файл существует и принадлежит действительному идентификатору пользователя
-r filename - проверить, является ли файл доступным для чтения
-S filename - проверить, является ли файл сокет
-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 

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




scripting