- 7.2. Операции проверки файлов
- Примечания
- Как проверить, существует ли файл или каталог в Bash
- Проверьте, существует ли файл
- Проверить, существует ли каталог
- Проверьте, не существует ли файла
- Проверьте, существует ли несколько файлов
- Операторы проверки файлов
- Выводы
- Как мне узнать, что обычный файл не существует в Bash?
- 17 ответов
- Блог системного администратора Windows/Linux/FreeBSD
- Shell-скрипт с условием проверки наличия файла для Linux/FreeBSD
- Похожие записи:
- Shell-скрипт с условием проверки наличия файла для Linux/FreeBSD : 8 комментариев
7.2. Операции проверки файлов
Возвращает true если.
обычный файл (не каталог и не файл устройства)
ненулевой размер файла
файл является каталогом
файл является блочным устройством (floppy, cdrom и т.п.)
файл является символьным устройством (клавиатура, модем, звуковая карта и т.п.)
файл является каналом
файл является символической ссылкой
файл является символической ссылкой
файл является сокетом
файл (дескриптор) связан с терминальным устройством
Этот ключ может использоваться для проверки — является ли файл стандартным устройством ввода stdin ( [ -t 0 ]) или стандартным устройством вывода stdout ( [ -t 1 ]).
файл доступен для чтения ( пользователю, запустившему сценарий )
файл доступен для записи (пользователю, запустившему сценарий)
файл доступен для исполнения (пользователю, запустившему сценарий)
set-group-id (sgid) флаг для файла или каталога установлен
Если для каталога установлен флаг sgid, то файлы, создаваемые в таком каталоге, наследуют идентификатор группы каталога, который может не совпадать с идентификатором группы, к которой принадлежит пользователь, создавший файл. Это может быть полезно для каталогов, в которых хранятся файлы, общедоступные для группы пользователей.
set-user-id (suid) флаг для файла установлен
Установленный флаг suid приводит к изменению привилегий запущенного процесса на привилегии владельца исполняемого файла. Исполняемые файлы, владельцем которых является root , с установленным флагом set-user-id запускаются с привилегиями root , даже если их запускает обычный пользователь. [1] Это может оказаться полезным для некоторых программ (таких как pppd и cdrecord), которые осуществляют доступ к аппаратной части компьютера. В случае отсутствия флага suid , программы не смогут быть запущены рядовым пользователем, не обладающим привилегиями root.
Файл с установленным флагом suid отображается с включенным флагом s в поле прав доступа.
флаг sticky bit (бит фиксации) установлен
Общеизвестно, что флаг «sticky bit» — это специальный тип прав доступа к файлам. Программы с установленным флагом «sticky bit» остаются в системном кэше после своего завершения, обеспечивая тем самым более быстрый запуск программы. [2] Если флаг установлен для каталога, то это приводит к ограничению прав на запись. Установленный флаг «sticky bit» отображается в виде символа t в поле прав доступа.
Если пользователь не является владельцем каталога, с установленным «sticky bit», но имеет право на запись в каталог, то он может удалять только те файлы в каталоге, владельцем которых он является. Это предотвращает удаление и перезапись «чужих» файлов в общедоступных каталогах, таких как /tmp.
вы являетесь владельцем файла
вы принадлежите к той же группе, что и файл
файл был модифицирован с момента последнего чтения
файлы f1 и f2 являются «жесткими» ссылками на один и тот же файл
«НЕ» — логическое отрицание (инверсия) результатов всех вышеприведенных проверок (возвращается true если условие отсутствует).
Пример 7-4. Проверка «битых» ссылок
Примечания
С флагом suid , на двоичных исполняемых файлах, надо быть очень осторожным, поскольку это может быть небезопасным. Установка флага suid на файлы-сценарии не имеет никакого эффекта.
В современных UNIX-системах, «sticky bit» больше не используется для файлов, только для каталогов.
Источник
Как проверить, существует ли файл или каталог в Bash
Часто при написании сценариев оболочки вы можете оказаться в ситуации, когда вам нужно выполнить действие в зависимости от того, существует файл или нет.
В Bash вы можете использовать команду test, чтобы проверить, существует ли файл, и определить тип файла.
Команда test принимает одну из следующих синтаксических форм:
Если вы хотите, чтобы ваш сценарий был переносимым, вам следует предпочесть старую команду test [ , которая доступна во всех оболочках POSIX. Новая обновленная версия тестовой команды [[ (двойные скобки) поддерживается в большинстве современных систем, использующих Bash, Zsh и Ksh в качестве оболочки по умолчанию.
Проверьте, существует ли файл
При проверке существования файла наиболее часто используются операторы FILE -e и -f . Первый проверит, существует ли файл независимо от типа, а второй вернет истину, только если ФАЙЛ является обычным файлом (а не каталогом или устройством).
Наиболее удобочитаемый вариант при проверке существования файла — использование команды test в сочетании с оператором if . Любой из приведенных ниже фрагментов проверит, существует ли файл /etc/resolv.conf :
Если вы хотите выполнить другое действие в зависимости от того, существует файл или нет, просто используйте конструкцию if / then:
Вы также можете использовать команду test без оператора if. Команда после оператора && будет выполнена только в том случае, если статус выхода тестовой команды — истина,
Если вы хотите запустить серию команд после оператора && просто заключите команды в фигурные скобки, разделенные ; или && :
Напротив && , оператор после || Оператор будет выполняться только в том случае, если статус выхода тестовой команды false .
Проверить, существует ли каталог
Операторы -d позволяют вам проверить, является ли файл каталогом или нет.
Например, чтобы проверить, существует ли каталог /etc/docker вы должны использовать:
Вы также можете использовать двойные скобки [[ вместо одинарной [ .
Проверьте, не существует ли файла
Как и во многих других языках, тестовое выражение может быть отменено с помощью ! (восклицательный знак) оператор логического НЕ:
То же, что и выше:
Проверьте, существует ли несколько файлов
Вместо использования сложных вложенных конструкций if / else вы можете использовать -a (или && с [[ ), чтобы проверить, существует ли несколько файлов:
Эквивалентные варианты без использования оператора IF:
Операторы проверки файлов
Команда test включает в себя следующие операторы FILE, которые позволяют проверять файлы определенных типов:
- -b FILE — Истина, если ФАЙЛ существует и является специальным блочным файлом.
- -c FILE — Истина, если ФАЙЛ существует и является файлом специальных символов.
- -d FILE — Истина, если ФАЙЛ существует и является каталогом.
- -e FILE — Истина, если ФАЙЛ существует и является файлом, независимо от типа (узел, каталог, сокет и т. д.).
- -f FILE — Истина, если ФАЙЛ существует и является обычным файлом (не каталогом или устройством).
- -G FILE — Истина, если ФАЙЛ существует и имеет ту же группу, что и пользователь, выполняющий команду.
- -h FILE — Истина, если ФАЙЛ существует и является символической ссылкой.
- -g FILE — Истина, если ФАЙЛ существует и для него установлен флаг set-group-id ( sgid ).
- -k FILE — Истина, если ФАЙЛ существует и для него установлен флаг липкого бита.
- -L FILE — Истина, если ФАЙЛ существует и является символической ссылкой.
- -O FILE — Истина, если ФАЙЛ существует и принадлежит пользователю, выполняющему команду.
- -p FILE — Истина, если ФАЙЛ существует и является каналом.
- -r FILE — Истинно, если ФАЙЛ существует и доступен для чтения.
- -S FILE — Истина, если ФАЙЛ существует и является сокетом.
- -s FILE — Истина, если ФАЙЛ существует и имеет ненулевой размер.
- -u FILE — Истинно, если ФАЙЛ существует и установлен флаг set-user-id ( suid ).
- -w FILE — Истина, если ФАЙЛ существует и доступен для записи.
- -x FILE — Истина, если ФАЙЛ существует и является исполняемым.
Выводы
В этом руководстве мы показали вам, как проверить, существует ли файл или каталог в Bash.
Если у вас есть какие-либо вопросы или отзывы, не стесняйтесь оставлять комментарии.
Источник
Как мне узнать, что обычный файл не существует в Bash?
Я использовал следующий скрипт, чтобы проверить, существует ли файл:
Какой правильный синтаксис использовать, если я только хочу проверить, существует ли файл не ?
17 ответов
Команда тест ( [ здесь) имеет «не» логический оператор, который является восклицательным знаком (аналогично многим другим языкам). Попробуйте это:
Тестирование файлов Bash
-b filename — заблокировать специальный файл
-c filename — файл специальных символов
-d directoryname — проверка существования каталога
-e filename — Проверить существование файла независимо от его типа (узел, каталог, сокет и т. Д.)
-f filename — проверка на наличие обычного файла, а не каталога
-G filename — проверка, существует ли файл и принадлежит ли он эффективный идентификатор группы
-G filename set-group-id — True, если файл существует и является идентификатором группы-набора
-k filename — Sticky bit
-L filename — Символическая ссылка
—- +: = 9 =: + —- — True, если файл существует и принадлежит действующему идентификатору пользователя
-O filename — проверить, доступен ли файл для чтения.
-r filename — проверить, является ли файл сокетом
-S filename — проверить, не равен ли файл ненулевому размеру
-s filename — проверьте, установлен ли бит набора идентификаторов пользователя
-u filename — проверить, доступен ли файл для записи
-w filename — проверить, является ли файл исполняемым
Как использовать:
тестовое выражение можно отменить, используя оператор #!/bin/bash file=./file if [ -e «$file» ]; then echo «File exists» else echo «File does not exist» fi
Вы можете отменить выражение с помощью «!»:
Соответствующей справочной страницей является man test или, что эквивалентно, man [ — или help test или help [ для встроенной команды bash.
Также возможно, что файл является неработающей символической ссылкой или нерегулярным файлом, например, например. розетка, устройство или fifo. Например, чтобы добавить проверку на битые символические ссылки:
Стоит отметить, что если вам нужно выполнить одну команду, вы можете сократить
Я предпочитаю использовать следующий однострочный текст в формате, совместимом с POSIX :
Для пары команд, как я сделал бы в сценарии:
Как только я начал это делать, я уже редко использую полностью типизированный синтаксис !!
Чтобы проверить существование файла, параметр может быть одним из следующих:
Все приведенные ниже тесты применимы к обычным файлам, каталогам и символическим ссылкам:
Будьте осторожны с запуском test для переменной без кавычек, поскольку это может привести к неожиданным результатам:
Рекомендуется, чтобы проверяемая переменная была заключена в двойные кавычки:
Вы можете сделать это:
Если вы хотите проверить оба файла и папки, используйте -e вместо -f . -e возвращает true для обычных файлов, каталогов, сокетов, специальных символов, блокированных специальных файлов и т. д.
Есть три различных способа сделать это:
Отмените статус выхода с помощью bash (другой ответ не сказал этого):
Отложите тест внутри команды теста [ (именно так большинство ответов представили ранее):
Действуйте, чтобы результат теста был отрицательным ( || вместо && ):
Это выглядит глупо (IMO), не используйте его, если ваш код не должен переноситься на оболочку Bourne (например, /bin/sh Solaris 10 или более ранней версии), в котором отсутствовал оператор отрицания конвейера ( ! ):
команда [ выполняет команду stat() (не lstat() ) системный вызов для пути, сохраненного в $file и возвращает true , если этот системный вызов завершился успешно, и тип файла, возвращаемый stat() является «регулярным».
Таким образом, если [ -f «$file» ] возвращает true, вы можете сказать, что файл существует и является обычным файлом или символической ссылкой, в конечном итоге преобразующейся в обычный файл (или, по крайней мере, это было во время stat() ).
Однако, если он возвращает false (или если [ ! -f «$file» ] или ! [ -f «$file» ] верните true), есть много разных возможностей:
- файл не существует
- файл существует, но не является обычным файлом
- файл существует, но у вас нет разрешения на поиск в родительском каталоге
- файл существует, но путь к нему слишком длинный
- файл является символической ссылкой на обычный файл, но у вас нет разрешения на поиск в некоторых каталогах, связанных с разрешением символической ссылки.
- . любая другая причина, по которой системный вызов stat() может завершиться неудачей.
Короче говоря, это должно быть:
Чтобы точно знать, что файл не существует, нам потребуется системный вызов stat() для возврата с кодом ошибки ENOENT ( ENOTDIR говорит нам об одном из Компоненты пути не каталог, это другой случай, когда мы можем сказать, что файл не существует по этому пути). К сожалению, команда [ не сообщает нам об этом. Он вернет false, независимо от того, является ли код ошибки ENOENT, EACCESS (разрешение отклонено), ENAMETOOLONG или что-то еще.
Тест [ -e «$file» ] также можно выполнить с помощью ls -Ld — «$file» > /dev/null . В этом случае ls расскажет вам, почему stat() не удалось, хотя информация не может быть легко использована программно:
По крайней мере ls говорит мне, что это не потому, что файл не существует, потому что он выходит из строя. Это потому, что он не может определить, существует файл или нет. Команда [ просто проигнорировала проблему.
С помощью оболочки zsh вы можете запросить код ошибки с помощью $ERRNO специальная переменная после неудачной команды [ и декодировать это число с помощью $errnos специальный массив в модуле zsh/system :
Чтобы отменить тест, используйте «!». Это эквивалентно «не» логическому оператору в других языках. Попробуйте это:
Или написано немного по-другому:
Или вы можете использовать:
Или, прижимая все вместе:
Который может быть записан (используя операторы «и»: & &) как:
Источник
Блог системного администратора Windows/Linux/FreeBSD
Shell-скрипт с условием проверки наличия файла для Linux/FreeBSD
Представлю вам скрипт, который архивирует файл, если он есть в заданной директории. Если файла нет — архив не создается.
Остальные ключи проверки файлов/каталогов:
Второй вариант bash-скрипта для проверки условия существования файлов и их архивирования при наличии:
Третий вариант проверки условия существования любых файлов в каталоге:
#Задаем переменную директории
DIR=/000/test/test
#вычисляем количество файлов, которые есть в заданной директории
filecount=`find $DIR -type f | wc -l`
#если количество файлов равно нулю, то есть их нет, то выдается сообщение
if [ $filecount -eq 0 ];
then
echo «Файлов нет, выполняем скрипт дальше»
else
echo «Есть файлы, прекращаем работу скрипта» && exit
fi
Четвертый вариант проверки условия существования любых файлов в каталоге с бесконечным циклом:
while true
do
case `find $DIR -type f | wc -l` in
0 ) echo «no file» ;; #Если файлов нет — выводится сообщение (или можно подставить любой ваш скрипт или команду)
* ) sleep 5 ;; #если файлы в каталоге есть — ждем 5 секунд и дальше проверяем по-новому (к первому шагу)
esac
done
exit 0
Похожие записи:
Shell-скрипт с условием проверки наличия файла для Linux/FreeBSD : 8 комментариев
Подскажите, а как будет выглядеть скрипт, который не даст дальнейшее выполнение основного скрипта, пока в указанном каталоге присутствуют файлы (любые), с любым именем и расширением?
Алексей, я добавил в статью вариант под вашу нужду. Пойдет?
Третий вариант, я думаю тоже возьму на заметку, но
если можно покажите пример, в котором бы
был как я понимаю бесконечный цикл проверки на наличия файлов.
То есть почти как третий вариант, только если файлы есть, то работа скрипта не прекращалась вообще, а допустим был бы sleep 5 и после него проверка повторялась и так до тех пор пока каталог не будет пустым и только тогда пойдёт выполнение скрипта далее.
Четвертый вариант пойдет? Я проверил — работает так, как вам нужно, если я правильно понял.
То что надо!
Спасибо
Не могу понять, пишу это на роутере.
Под sh выполняется всё корректно find $DIR -type f | wc -l,
а когда сам роутер выполняет эту команду, то почему то
она всё время пишет ноль файлов в каталоге, хотя они там есть.
Если быть точнее, то пишу скрипт:
filecount=`find /opt/var/spool/sms/failed/ -type f | wc -l`
echo -e $filecount >> /tmp/status
если данный скрипт выполнить под ssh, то всё ок, а если
его выполняет cron, то всё время получаю ноль.
Вроде разобрался, указал до команды find полный путь.
Источник