Гид по технологиям

Тестовые операторы файлов в Linux — проверка с помощью -e, -s, -d, -h, -r, -O

• 6 min read • Linux • Обновлено 22 Nov 2025
Тестовые операторы файлов в Linux — -e -s -d -h -r -O
Тестовые операторы файлов в Linux — -e -s -d -h -r -O

Обложка: тестирование файлов в Linux

Введение

Тестовые операторы файлов в оболочке Bash и POSIX-совместимых shell используются для принятия решений в скриптах: существует ли файл, пуст ли он, является ли он директорией или символической ссылкой, доступен ли он для чтения и принадлежит ли текущему пользователю. Правильное использование операторов делает скрипты надежными и безопасными.

Кратко о терминах:

  • Тестовый оператор — выражение вида [ -e path ] или [[ -e path ]], возвращающее успешный код выхода (0) при выполнении условия.
  • Символическая ссылка — файл, содержащий путь на другой файл.

Важно: в большинстве реализаций -h и -L эквивалентны (проверяют символическую ссылку). Некоторые встроенные реализации могут незначительно отличаться, поэтому тестируйте в вашей среде.

Какие операторы мы рассмотрим

  • -e — файл существует
  • -s — файл существует и не пустой
  • -d — путь — директория
  • -h — путь — символическая ссылка (альтернатива: -L)
  • -r — файл читаем текущим пользователем (euid)
  • -O — файл принадлежит текущему пользователю (euid)

Общая методика: как организовать проверку в скрипте

Мини-методология:

  1. Валидация входных параметров (проверить, что переменная с путём непуста).
  2. Использовать кавычки вокруг переменных: “$file”.
  3. Использовать явные условия с понятным сообщением об ошибке.
  4. Логировать причины отказа (exit code ≠ 0) и при необходимости выдавать рекомендации.

Простой шаблон:

#!/usr/bin/env bash
file="$1"
if [ -z "$file" ]; then
  echo "Укажите путь к файлу" >&2
  exit 2
fi

if [ -e "$file" ]; then
  echo "$file найден"
else
  echo "$file не найден" >&2
  exit 1
fi

Подробные примеры и объяснения

1) Проверка существования: -e

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

Пример:

file="Test.txt"
if [ -e "$file" ]; then
  echo "True: $file существует"
else
  echo "False: $file не найден"
fi

Запуск:

$ touch Test.txt
$ bash FileTestOperators.sh

Окно файлового менеджера, файлы в домашней директории

Заметки:

  • -e не различает тип: директория, обычный файл или ссылка — лишь проверяет существование.
  • Для POSIX-строгих скриптов используйте single-bracket [ … ] или команду test.

2) Проверка непустоты: -s

Назначение: файл существует и имеет размер > 0 байт.

Пример:

file="Test.txt"
if [ -s "$file" ]; then
  echo "True: $file не пустой"
else
  echo "False: $file пустой или не существует"
fi

Если файл пуст — оператор вернёт False. Добавление текста в файл изменит результат на True.

Скрипт с оператором -s

Дополнительная проверка содержимого:

cat Test.txt
file Test.txt

3) Проверка директории: -d

Назначение: проверить, что путь указывает на директорию.

Пример:

file="Test.txt"
if [ -d "$file" ]; then
  echo "True: $file — директория"
else
  echo "False: $file не является директорией"
fi

Если путь — обычный файл, результат будет False.

Скрипт с оператором -d

4) Проверка символической ссылки: -h (или -L)

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

Создание примера:

touch SymbolicFile.sh
ln -s SymbolicFile.sh NewSymbolicFile.sh
file="NewSymbolicFile.sh"
if [ -h "$file" ]; then
  echo "True: $file — символическая ссылка"
else
  echo "False: $file не ссылка"
fi

Команда ls -l покажет стрелку к целевому файлу.

Файл SymbolicFile.sh в домашней директории

Результат ls -l, отображение символической ссылки

Вывод после создания символической ссылки

Файлы и ссылка NewSymbolicFile.sh рядом с оригиналом

Примечание: -h и -L эквивалентны в большинстве реализаций test. Если хотите проверить файл, на который указывает ссылка, используйте проверку самого целевого пути.

5) Проверка на читаемость: -r

Назначение: проверить, может ли текущий процесс прочитать файл (основываясь на effective UID/GID и ACL).

Пример:

file="Test.txt"
if [ -r "$file" ]; then
  echo "True: $file читаем"
else
  echo "False: $file нечитаем или не существует"
fi

Скрипт проверки читаемости файла -r

Важно: для записи и выполнения используйте -w и -x соответственно.

6) Проверка владельца: -O

Назначение: убедиться, что файл принадлежит текущему пользователю (effective UID).

Пример:

file="Test.txt"
if [ -O "$file" ]; then
  echo "True: $file принадлежит текущему пользователю"
else
  echo "False: $file принадлежит другому пользователю"
fi

Проверка владельца файла с оператором -O

Замечание: -O сравнивает владельца с effective UID процесса. Если скрипт запускается sudo, результат может отличаться.

Частые ошибки и когда проверки дают неожиданный результат

  • Забытые кавычки: [ -e $file ] при пути с пробелами разобьёт аргумент.
  • Различие real vs effective ID: операции с sudo могут менять результат -O, -r, -w.
  • -e вернёт True и для симлинка, даже если цель удалена (если сама ссылка существует).
  • Проверка прав через тест не учитывает SELinux/прочие расширенные политики.

Важно: тестовые операторы оценивают состояние на момент выполнения. Между проверкой и использованием файла возможна гонка (TOCTOU). Для критичных операций используйте атомарные системные вызовы.

Чек-лист для разработчика/администратора

  • Проверить входной параметр и экранировать его.
  • Использовать кавычки вокруг переменных.
  • Логировать причину отказа и код выхода.
  • При необходимости использовать mkdir -p или touch с проверкой ошибок.
  • Для операций с правами понимать влияние sudo/euid.

Быстрая шпаргалка (cheat sheet)

  • [ -e FILE ] — существует (файл/директория/ссылка)
  • [ -s FILE ] — существует и размер > 0
  • [ -d FILE ] — это директория
  • [ -h FILE ] — это символическая ссылка (синоним: -L)
  • [ -r FILE ] — читаемо текущим пользователем
  • [ -w FILE ] — доступно для записи
  • [ -x FILE ] — исполняемо
  • [ -O FILE ] — владелец — текущий пользователь

Роль-ориентированные контрольные пункты

Для разработчика:

  • Добавить проверки наличия файла перед чтением.
  • Обрабатывать ошибочные коды и выводить понятные сообщения.

Для системного администратора:

  • Проверять владельца и права перед запуском автоматизированных задач.
  • Учитывать влияние sudo и cron (разные euid/egid).

Для DevOps/CI:

  • Использовать тесты в pipeline перед деплоем (наличие конфигов, отсутствие пустых файлов, корректные права).

Сценарий инцидента: файл конфигурации отсутствует

Runbook (быстрые шаги):

  1. Проверить существование: [ -e /etc/myapp/conf.json ]
  2. Если отсутствует — проверить историю изменений (git, backup).
  3. Восстановить из резервной копии или создать шаблон конфигурации.
  4. Проверить права доступа: владельцем должен быть сервисный пользователь; права 640/600 в зависимости от требований.
  5. Перезапустить сервис и проверить логи.

Критерии приёмки:

  • Файл существует и не пустой
  • Владелец и права соответствуют политике
  • Сервис успешно стартует

Тест-кейсы для валидации скриптов

  1. Путь пустой -> скрипт возвращает код 2 и понятное сообщение.
  2. Файл не существует -> код 1 и сообщение об отсутствии.
  3. Файл существует и пуст -> -s даёт False, -e даёт True.
  4. Файл — символическая ссылка -> -h True, -e True.
  5. Файл принадлежит другому пользователю -> -O False.
  6. Запуск через sudo -> поведение -O может измениться.

Руководство по безопасности и приватности

  • Никогда не логируйте содержимое конфиденциальных файлов.
  • При автоматическом создании файлов задавайте минимально необходимые права (умолчание 600/640).
  • Учтите SELinux/AppArmor: тестовые операторы не отражают дополнительных политик безопасности.

Примеры продвинутых шаблонов

Атомарная обработка с временной блокировкой (примитивный подход для избежания гонок):

file="/var/lib/myapp/state"
lockdir="${file}.lock"
if mkdir "$lockdir" 2>/dev/null; then
  trap 'rmdir "$lockdir"' EXIT
  # безопасно читать/писать файл
  if [ -e "$file" ]; then
    # работа с файлом
    :
  fi
else
  echo "Не удалось получить блокировку, другой процесс работает" >&2
  exit 3
fi

Мероприятие для выбора действия (decision tree)

flowchart TD
  A[Есть путь?] -->|нет| B[Ошибка: укажите путь]
  A -->|да| C{Существует?}
  C -->|нет| D[Создать/восстановить]
  C -->|да| E{Это директория?}
  E -->|да| F[Операции с директориями]
  E -->|нет| G{Симлинк?}
  G -->|да| H[Проверить цель ссылки]
  G -->|нет| I{Пустой?}
  I -->|да| J[Содержимое отсутствует — заполнить/ошибка]
  I -->|нет| K[Проверки прав и владельца]
  K -->|OK| L[Продолжить]
  K -->|не OK| M[Исправить права/владельца]

Короткая галерея крайних случаев

  • Файл существует, но цель симлинка удалена: -e вернёт True для ссылки, но доступ к содержимому приведёт к ошибке.
  • Файл читаем, но SELinux запрещает доступ — тест -r вернёт True, а реальный доступ может быть заблокирован.
  • Скрипт запускается cron’ом от другого пользователя — права и владельцы влияют на поведение.

1‑строчный глоссарий

  • test/[] — встроенный тест в shell; возвращает код выхода 0 при истинности.
  • euid — effective UID процесса, влияет на проверку -r/-w/-O.
  • TOCTOU — time-of-check to time-of-use, гонка между проверкой и использованием.

Заключение

Тестовые операторы файлов — базовый и мощный инструмент для написания надёжных shell-скриптов. Простые проверки (-e, -s, -d, -h, -r, -O) позволяют избегать ошибок и защищают от типичных проблем: отсутствия файлов, неправильных прав и неожиданного типа объекта. Соблюдайте практики безопасности, используйте кавычки и логирование, и ваши сценарии будут предсказуемо работать в разных средах.

Важно: всегда тестируйте скрипты в целевой среде, особенно если используются sudo, cron или контейнеры.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро