Команда test в линукс

Обновлено: 03.07.2024

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Выводы

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

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

Как уже говорилось выше, для построения произвольных алгоритмов необходимо иметь операторы проверки условий. Оболочка bash поддерживает операторы выбора if … then … else и case , а также операторы организации циклов for , while , until , благодаря чему она превращается в мощный язык программирования.

5.8.1 Операторы if и test (или [ ])

Конструкция условного оператора в слегка упрощенном виде выглядит так:

if list1 then list2 else list3 fi

где list1 , list2 и list3 — это последовательности команд, разделенные запятыми и оканчивающиеся точкой с запятой или символом новой строки. Кроме того, эти последовательности могут быть заключены в фигурные скобки: .

Оператор if проверяет значение, возвращаемое командами из list1 . Если в этом списке несколько команд, то проверяется значение, возвращаемое последней командой списка. Если это значение равно 0, то будут выполняться команды из list2 ; если это значение не нулевое, будут выполнены команды из list3 . Значение, возвращаемой таким составным оператором if , совпадает со значением, выдаваемым последней командой выполняемой последовательности.

Полный формат команды if имеет вид:

if list then list [ elif list then list ] . [ else list ] fi

(здесь квадратные скобки означают только необязательность присутствия в операторе того, что в них содержится).

В качестве выражения, которое стоит сразу после if или elif , часто используется команда test , которая может обозначаться также квадратными скобками [ ]. Команда test выполняет вычисление некоторого выражения и возвращает значение 0, если выражение истинно, и 1 в противном случае. Выражение передается программе test как аргумент. Вместо того, чтобы писать

можно заключить выражение в квадратные скобки:

Заметьте, что test и [ — это два имени одной и той же программы, а не какое-то магическое преобразование, выполняемое оболочкой bash (только синтаксис [ требует, чтобы была поставлена закрывающая скобка). Заметьте также, что вместо test в конструкции if может быть использована любая программа.

В заключение приведем пример использования оператора if :

if [ -e textmode2.htm ] ; then

Об операторе test (или […]) надо бы поговорить особо.

5.8.2 Оператор test и условные выражения

Условные выражения, используемые в операторе test , строятся на основе проверки файловых атрибутов, сравнения строк и обычных арифметических сравнений. Сложные выражения строятся из следующих унарных или бинарных операций ("элементарных кирпичиков"):

Верно, если файл с именем file существует.

Верно, если file существует и является специальным файлом блочного устройства.

Верно, если file существует и является специальным файлом символьного устройства.

Верно, если file существует и является каталогом.

Верно, если файл с именем file существует.

Верно, если файл с именем file существует и является обычным файлом.

Верно, если файл с именем file существует и для него установлен бит смены группы.

Верно, если файл с именем file существует и является символической ссылкой.

Верно, если файл с именем file существует и для него установлен "sticky'' bit.

Верно, если файл с именем file существует и является именованным каналом (FIFO).

Верно, если файл с именем file существует и для него установлено право на чтение

Верно, если файл с именем file существует и его размер больше нуля .

Верно, если дескриптор файла fd открыт и указывает на терминал.

Верно, если файл с именем file существует и для него установлен бит смены пользователя.

Верно, если файл с именем file существует и для него установлено право на запись.

Верно, если файл с именем file существует и является исполняемым .

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

Верно, если файл с именем file существует и принадлежит группе, определяемой эффективным идентификатором группы.

Верно, если файл с именем file существует и является сокетом.

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

Верно, если файл file1 имеет более позднее время модификации, чем file2 .

Верно, если файл file1 старше , чем file2 .

Верно, если файлы file1 и file2 имеют одинаковые номера устройств и индексных дескрипторов (inode).

Верно, если задействована опция оболочки optname . Пояснения см. на странице man bash.

Верно, если длина строки равна нулю.

Верно, если длина строки не равна нулю.

Верно, если строки совпадают. Вместо == может использоваться = .

Верно, если строки не совпадают.

Верно, если строка string1 лексикографически предшествует строке string2 (для текущей локали).

Верно, если строка string1 лексикографически стоит после строки string2 (для текущей локали).

Здесь OP — э то одна из операций арифметического сравнения: -eq (равно), -ne (не равно), -lt (меньше чем), -le (меньше или равно), -gt (больше), -ge (больше или равно). В качестве аргументов могут использоваться положительные или отрицательные целые.

Из этих элементарных условных выражений можно строить сколь угодно сложные с помощью обычных логических операций ОТРИЦАНИЯ, И и ИЛИ:

Булевский оператор отрицания.

Булевский оператор AND (И). Верен, если верны оба выражения.

Булевский оператор OR (ИЛИ). Верен, если верно любое из двух выражений.

Такие же условные выражения используются и в операторах while и until , которые мы рассмотрим чуть ниже.

5.8.3 Оператор case

Формат оператора case таков:

case word in [ [(] pattern [ | pattern ] . ) list ;; ] . esac

Команда case вначале производит раскрытие слова word , и пытается сопоставить результат с каждым из образцов pattern поочередно. После нахождения первого совпадения дальнейшие проверки не производятся, выполняется список команд, стоящий после того образца, с которым обнаружено совпадение. Значение, возвращаемое оператором, равно 0, если совпадений с образцами не обнаружено. В противном случае возвращается значение, выдаваемое последней командой из соответствующего списка.

Следующий пример использования оператора case заимствован из системного скрипта /etc/rc.d/rc.sysinit.

Если переменная принимает значение yes или true, то будет выполнена первая пара команд, а если ее значение равно no или false – вторая пара.

5.8.4 Оператор select

Оператор select позволяет организовать интерактивное взаимодействие с пользователем. Он имеет следующий формат:

select name [ in word; ] do list ; done

Вначале из шаблона word формируется список слов, соответствующих шаблону. Этот набор слов выводится в стандартный поток ошибок, причем каждое слово сопровождается порядковым номером. Если шаблон word пропущен, таким же образом выводятся позиционные параметры. После этого выдается стандартное приглашение PS3, и оболочка ожидает ввода строки на стандартном вводе. Если введенная строка содержит число, соответствующее одному из отображенных слов, то переменной name присваивается значение, равное этому слову. Если введена пустая строка, то номера и соответствующие слова выводятся заново. Если введено любое другое значение, переменной name присваивается нулевое значение. Введенная пользователем строка запоминается в переменой REPLY . Список команд list выполняется с выбранным значением переменной name .

Вот небольшой скрипт:

echo "Какую ОС Вы предпочитаете?"

echo "Вы бы выбрали $var"

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

Нажмите любую из 4 предложенных цифр (1,2,3,4). Если вы, например, введете 1, то увидите собщение:

“Вы бы выбрали Linux”

5.8.5 Оператор for

Оператор for работает немного не так, как в обычных языках программирования. Вместо того, чтобы организовывать увеличение или уменьшение на единицу значения некоторой переменной при каждом проходе цикла, он при каждом проходе цикла присваивает переменной очередное значение из заданного списка слов. В целом конструкция выглядит примерно так:

for name in words do list done.

Правила построения списков команд ( list ) такие же, как и в операторе if .

Пример . Следующий скрипт создает файлы foo_1, foo_2 и foo_3:

for a in 1 2 3 ; do

В общем случае оператор for имеет формат:

for name [ in word; ] do list ; done

Вначале производится раскрытие слова word в соответствии с правилами раскрытия выражений, приведенными выше. Затем переменной name поочередно присваиваются полученные значения, и каждый раз выполняется список команд l ist . Если " in word " пропущено, то список команд list выполняется один раз для каждого позиционного параметра, который задан.

В Linux имеется программа seq , которая воспринимает в качестве аргументов два числа и выдает последовательность всех чисел, расположенных между заданными. С помощью этой команды можно заставить for в bash работать точно так же, как аналогичный оператор работает в обычных языках программирования. Для этого достаточно записать цикл for следующим образом:

for a in $( seq 1 10 ) ; do

Эта команда выводит на экран содержимое 10-ти файлов: " file_1", . "file_10".

5.8.6 Операторы while и until

Оператор while работает подобно if , только выполнение операторов из списка list2 циклически продолжается до тех пор, пока верно условие, и прерывается, если условие не верно. Конструкция выглядит следующим образом:

while list1 do list2 done.

while [ -d mydirectory ] ; do

ls -l mydirectory >> logfile

echo -- SEPARATOR -- >> logfile

Такая программа будет протоколировать содержание каталога "mydirectory" ежеминутно до тех пор, пока директория существует.

Оператор until аналогичен оператору while :

until list1 do list2 done.

Отличие заключается в том, что результат, возвращаемый при выполнении списка операторов list1 , берется с отрицанием: list2 выполняется в том случае, если последняя команда в списке list1 возвращает ненулевой статус выхода.

5.8.7 Функции

Синтаксис

Оболочка bash позволяет пользователю создавать собственные функции. Функции ведут себя и используются точно так же, как обычные команды оболочки, т. е. мы можем сами создавать новые команды. Функции конструируются следующим образом:

Причем слово function не обязательно, name определяет имя функции, по которому к ней можно обращаться, а тело функции состоит из списка команд list , находящегося между < и >. Этот список команд выполняется каждый раз, когда имя name задано как имя вызываемой команды. Отметим, что функции могут задаваться рекурсивно, так что разрешено вызывать функцию, которую мы задаем, внутри нее самой.

Функции выполняются в контексте текущей оболочки: для интерпретации функции новый процесс не запускается (в отличие от выполнения скриптов оболочки).

Аргументы

Локальные переменные (local)

Если мы хотим создать локальный параметр, можно использовать ключевое слово local . Синтаксис ее задания точно такой же, как и для обычных параметров, только определению предшествует ключевое слово local: local name=value .

Вот пример задания функции, реализующей упоминавшуюся выше команду seq :

while [ $2 != $I ]; do

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

Функция вычисления факториала fact

Еще один пример:

Это функция факториала, пример рекурсивной функции. Обратите внимание на арифметическое расширение и подстановку команд.

Выходит со статусом, определяемым ВЫРАЖЕНИЕМ. --help вывести справку и закончить работу --version вывести информацию о версии и закончить работу

Если ВЫРАЖЕНИЕ не указано, подразумевается значение ЛОЖЬ (false). ВЫРАЖЕНИЕ принимает значение ИСТИНА (true) или ЛОЖЬ и определяет статус выхода программы. Выражения могут быть такими: ( ВЫРАЖЕНИЕ ) Проверка ВЫРАЖЕНИЯ ! ВЫРАЖЕНИЕ Логическое отрицание ВЫРАЖЕНИЯ ВЫРАЖЕНИЕ1 -a ВЫРАЖЕНИЕ2 Логическое И для ВЫРАЖЕНИЕ1 и ВЫРАЖЕНИЕ2 ВЫРАЖЕНИЕ1 -o ВЫРАЖЕНИЕ2 Логическое ИЛИ для ВЫРАЖЕНИЕ1 и ВЫРАЖЕНИЕ2 [-n] СТРОКА длина СТРОКИ ненулевая СТРОКА аналогично -n СТРОКА -z СТРОКА длина СТРОКИ равна нулю СТРОКА1 = СТРОКА2 СТРОКИ совпадают СТРОКА1 != СТРОКА2 СТРОКИ не совпадают ЦЕЛОЕ1 -eq ЦЕЛОЕ2 ЦЕЛОЕ1 равно ЦЕЛОЕ2 ЦЕЛОЕ1 -ge ЦЕЛОЕ2 ЦЕЛОЕ1 больше или равно ЦЕЛОЕ2 ЦЕЛОЕ1 -gt ЦЕЛОЕ2 ЦЕЛОЕ1 больше ЦЕЛОЕ2 ЦЕЛОЕ1 -le ЦЕЛОЕ2 ЦЕЛОЕ1 меньше или равно ЦЕЛОЕ2 ЦЕЛОЕ1 -lt ЦЕЛОЕ2 ЦЕЛОЕ1 меньше ЦЕЛОЕ2 ЦЕЛОЕ1 -ne ЦЕЛОЕ2 ЦЕЛОЕ1 не равно ЦЕЛОЕ2 ФАЙЛ1 -ef ФАЙЛ2 ФАЙЛ1 и ФАЙЛ2 имеют одно и то же устройство и номера inode ФАЙЛ1 -nt ФАЙЛ2 ФАЙЛ1 новее (по дате изменения), чем ФАЙЛ2 ФАЙЛ1 -ot ФАЙЛ2 ФАЙЛ1 старше (по дате изменения), чем ФАЙЛ2 -b ФАЙЛ ФАЙЛ существует и является блочным устройством -c ФАЙЛ ФАЙЛ существует и является символьным устройством -d ФАЙЛ ФАЙЛ существует и является каталогом -e ФАЙЛ ФАЙЛ существует -f ФАЙЛ ФАЙЛ существует и является обычным файлом -g ФАЙЛ ФАЙЛ существует и является set-group-ID -G ФАЙЛ ФАЙЛ существует и для него установлен эффективный идентификатор группы -h ФАЙЛ ФАЙЛ существует и является символической ссылкой (аналогично -L ) -k ФАЙЛ ФАЙЛ существует и для него установлен бит наследования (sticky bit) -L ФАЙЛ ФАЙЛ существует и является символической ссылкой -O ФАЙЛ ФАЙЛ существует и для него установлен эффективный идентификатор пользователя -p ФАЙЛ ФАЙЛ существует и является именованным каналом -r ФАЙЛ ФАЙЛ существует и доступен для чтения -s ФАЙЛ ФАЙЛ существует и ненулевой длины -S ФАЙЛ ФАЙЛ существует и является сокетом -t [FD] Описатель ФАЙЛА FD (по умолчанию stdout) открыт в терминале -u ФАЙЛ ФАЙЛ существует и для него установлен бит SUID -w ФАЙЛ ФАЙЛ существует и доступен для записи -x ФАЙЛ ФАЙЛ существует и доступен для исполнения

Кроме случаев, когда указываются опции -h и -L , выполняется разрешение символических ссылок. Помните, что для передачи круглых скобок необходимо предварять их обратной косой чертой. ЦЕЛОЕ может также быть и -l СТРОКИ, т.е. длиной СТРОКИ.

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

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

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

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

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


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

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

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


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

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

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

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

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


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

Выводы

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

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

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