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: проверить файл существует или нет):
Читайте также: