Bash как проверить наличие файла

Обновлено: 02.07.2024

В настоящее время у меня есть этот сценарий bash (который находится в моем домашнем каталоге, т.е. /home/fusion809/ , и я запускаю его как root, поскольку это необходимо для строк копирования значков):

Я хочу, чтобы этот сценарий копировал значки из моего каталога Pictures/Icons and logos в подкаталоги темы scalable (указанной в $B ) в /usr/share/icons . Однако, прежде чем он это сделает, я бы хотел, чтобы он создал каталог scalable в этих подкаталогах темы, если он еще не существует. Проблема в том, что другая часть условных выражений не читается должным образом, поскольку я продолжаю получать эту ошибку:

Если вам интересно, почему test -e . в условном выражении, он основан на учебнике по сценариям bash, за которым я следил.

2 ответа

Чтобы проверить, существует ли файл в bash, вы используете оператор -f . Для каталогов используйте -d . Пример использования:

Для получения дополнительной информации просто выполните man test .

Замечание о -e , этот тестовый оператор проверяет, существует ли файл. Хотя это может показаться хорошим выбором, лучше использовать -f , который вернет false, если файл не является обычным файлом. Например, /dev/null - это файл, а не обычный файл. В этом случае нежелательно, чтобы проверка вернула истину.

Примечание о переменных

Не забудьте также заключить переменные в кавычки, если у вас есть пробел или любой другой специальный символ, содержащийся в переменной, это может иметь нежелательные побочные эффекты. Поэтому, когда вы проверяете наличие файлов и каталогов, заключите файл / каталог в двойные кавычки. Что-то вроде [ -f "/path/to/some/$/" ] будет работать, а следующее не удастся, если в dir есть пробел: [ -f /path/to/some/$/ ] .

У вас есть синтаксическая ошибка в операторах управления. Предложение bash if имеет следующую структуру:

Или необязательно с предложением else :

Вы не можете опустить предложение then . Если вы хотите использовать только предложение else , вы должны отрицать это условие. Результатом является следующий код:

Здесь мы добавляем восклицательный знак ( ! ), чтобы перевернуть оценку выражения. Если выражение истинно, то же выражение, которому предшествует ! , вернет ложь и наоборот.

Вы не можете пропустить часть then оператора if , самым простым решением было бы просто отрицать тест

Я оставил его с -e (существует), но вы можете рассмотреть возможность использования -d для каталогов или -f для файлов и некоторой обработки ошибок, чтобы отловить что-то (например, / usr / share / icons / $ j / scaleable / существует, но по какой-то причине является файлом, а не каталогом.) Я также заметил, что в исходном коде вы потенциально пытаетесь скопировать несколько файлов в один:

Я оставил это в своем примере на тот случай, если вы уверены, что это всегда только один файл, и намеренно переименовываете его. В противном случае я бы предложил указать только целевой каталог.

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

В Bash вы можете использовать команду test, чтобы проверить, существует ли файл, и определить тип файла.

Команда test принимает одну из следующих синтаксических форм:

Если вы хотите, чтобы ваш сценарий был переносимым, вам следует предпочесть старую команду test [ , которая доступна во всех оболочках POSIX. Новая обновленная версия тестовой команды [[ (двойные скобки) поддерживается в большинстве современных систем, использующих Bash, Zsh и Ksh в качестве оболочки по умолчанию.

Проверьте, существует ли файл

При проверке существования файла наиболее часто используются операторы FILE -e и -f . Первый проверит, существует ли файл независимо от типа, а второй вернет истину, только если ФАЙЛ является обычным файлом (а не каталогом или устройством).

Если вы хотите выполнить другое действие в зависимости от того, существует файл или нет, просто используйте конструкцию if / then:

Всегда используйте двойные кавычки, чтобы избежать проблем при работе с файлами, в именах которых есть пробелы.

Если вы хотите запустить серию команд после оператора && просто заключите команды в фигурные скобки, разделенные ; или && :

Напротив && , оператор после || Оператор будет выполняться только в том случае, если статус выхода тестовой команды false .

Проверить, существует ли каталог

Операторы -d позволяют вам проверить, является ли файл каталогом или нет.

Например, чтобы проверить, существует ли каталог /etc/docker вы должны использовать:

Вы также можете использовать двойные скобки [[ вместо одинарной [ .

Проверьте, не существует ли файла

Как и во многих других языках, тестовое выражение может быть отменено с помощью ! (восклицательный знак) оператор логического НЕ:

То же, что и выше:

Проверьте, существует ли несколько файлов

Вместо использования сложных вложенных конструкций if / else вы можете использовать -a (или && с [[ ), чтобы проверить, существует ли несколько файлов:

Эквивалентные варианты без использования оператора IF:

Операторы проверки файлов

Команда test включает в себя следующие операторы FILE, которые позволяют проверять файлы определенных типов:

Выводы

В этом руководстве мы показали вам, как проверить, существует ли файл или каталог в Bash.

Если у вас есть какие-либо вопросы или отзывы, не стесняйтесь оставлять комментарии.

В операционных системах GNU/Linux любые объекты системы являются файлами. И проверка существования файла bash - наиболее мощный и широко применяемый инструмент для определения и сравнения в командном интерпретаторе.

В рамках интерпретатора Bash, как и в повседневном понимании людей, все объекты файловой системы являются, тем, чем они есть, каталогами, текстовыми документами и т.д. В этой статье будет рассмотрена проверка наличия файла Bash, а также его проверка на пустоту, и для этого используется команда test.

Проверка существования файла Bash

Начать стоит с простого и более общего метода. Параметр -e позволяет определить, существует ли указанный объект. Не имеет значения, является объект каталогом или файлом.

Пример работы кода:


Проверка наличия файла

Проверка файла Bash на то, является ли данный объект файлом (то есть существует ли файл), выполняется с помощью параметра -f.

Пример работы кода:


В сценарии проверяется, является ли $HOME файлом. Результат проверки отрицательный, после чего проверяется настоящий файл .bash_history, что уже возвращает истину.

На заметку: на практике предпочтительнее использовать сначала проверку на наличие объекта как такового, а затем — на его конкретный тип. Так можно избежать различных ошибок или неожиданных результатов работы программы.

Проверка файла на пустоту

Чтобы определить, является ли файл пустым, нужно выполнить проверку с помощью параметра -s. Это особенно важно, когда файл намечен на удаление. Здесь нужно быть очень внимательным к результатам, так как успешное выполнение этого параметра указывает на наличие данных.

Результат работы программы:


В этом скрипте файл создаётся командой touch, и при первой проверке на пустоту возвращается отрицательный результат. Затем в него записываются данные в виде команды date, после чего повторная проверка файла возвращает истину.

Выводы

В статье была рассмотрена проверка существования файла bash, а также его пустоты. Обе функции дополняют друг друга, поэтому использовать их в связке - эффективный приём.

Хороший тон в написании сценариев командного интерпретатора - сначала определить тип файла и его дальнейшую роль в программе, а затем уже проверять объект на существование.

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

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

Тестирование Файлов 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 - проверьте, является ли файл исполняемым

как использовать:

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

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

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

кроме того, возможно, что файл является сломанной символической ссылкой или нерегулярным файлом, например, сокетом, устройством или fifo. Например, чтобы добавить чек на сломанные символические ссылки:

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

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

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

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

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

все тесты ниже применяются к обычным файлам, каталогам и символическим ссылкам:

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

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

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

отрицание статуса выхода с bash (ни один другой ответ не сказал этого):

действуйте на результат отрицательного теста ( || вместо && ):

это выглядит глупо (IMO), не используйте его, если ваш код не должен быть переносным в оболочку Bourne (например, /bin/sh Solaris 10 или более ранних версий), которому не хватало оператора отрицания трубопровода ( ! ):

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

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

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

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

  • файл не существует
  • файл существует, но не является обычным файлом
  • файл существует, но у вас нет разрешения на поиск в Родительском каталоге
  • файл существует, но этот путь для доступа к нему слишком длинный
  • файл является символической ссылкой на обычный файл, но у вас нет разрешения на поиск для некоторых каталогов, участвующих в разрешении символической ссылки.
  • . любая другая причина, почему stat() системный вызов может завершиться неудачей.

короче говоря, это должно быть:

чтобы знать наверняка, что файл не существует, нам понадобится stat() системный вызов для возврата с кодом ошибки ENOENT ( ENOTDIR говорит нам, что один из компонентов пути не является каталогом, это еще один случай, когда мы можем сказать, что файл не существует по этому пути). К сожалению, [ команда не дает нам знать об этом. Он вернет false, является ли код ошибки ENOENT, EACCESS (разрешение отказано), ENAMETOOLONG или что-либо еще.

на [ -e "$file" ] тест также можно сделать с ls -Ld -- "$file" > /dev/null . В таком случае . --20--> скажет вам, почему stat() не удалось, хотя информация может быть легко использована программно:

по крайней мере ls говорит мне, что это не потому, что файл не существует, что он терпит неудачу. Потому что он не может сказать, существует файл или нет. The [ команда просто проигнорировала проблему.

С zsh shell, вы можете запросить код ошибки с помощью $ERRNO специальная переменная после сбоя [ команда и декодировать это число с помощью $errnos специальный массив в zsh/system модуль:

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

или написано немного по-другому:

или вы можете использовать:

или, пресинг все вместе:

который может быть записан (используя тогда "и" оператор:&&) как:

, который выглядит короче такой:

на test что может рассчитывать. Это сработало для меня (на основе Bash Shell: проверить файл существует или нет):

Читайте также: