Поиск документов в файловой системе

Поиск документов в файловой системе #

Файловая система представляет удобный механизм для хранения различных документов: для каждой категории данных можно выделить свой отдельный каталог, который далее можно поделить на подкаталоги и так далее. Мы также знаем, что можно организовать ссылки на документы из других разделов или на сами разделы с помощью символических ссылок.

Документы также могут появляться в результате работы различных скриптов: получение данных с других систем, целевой результат работы CI/CD систем и так далее. Такие данные обычно тоже хорошо структурированы, обычно согласно времени их создания или порядковому номеру.

Документы тоже могут входить в комплект поставки самого ПО или могут быть получены от третьих лиц.

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

Для решения подобных задач существуют специальные приложения, которые позволяют находить файлы на жёстком диске в соответствии с различными критериями. Глобально приложения можно разделить на 2 категории:

  • Поиск по базе данных: locale, подсистемы графических окружений Akonadi, Nepomuk и т.д. Эти инструменты проводят регулярную индексацию файловой системы и записывают результаты в базу данных. Когда пользователь даёт запрос на поиск файлов, то он происходит не по файловой системе, а базе данных. Возможности поиска ограничены информацией в базе данных, но происходят очень быстро.
  • Поиск по файловой системе: find, fd, grep и так далее. Данные инструменты при каждом запуске обращаются напрямую к файловой системе. Плюсом этих инструментов являются наиболее актуальные данные, однако скорость их работы напрямую зависит от объёма проверяемых данных.

Мы рассмотрим вторую категорию приложений, так как они позволяют получить точный результат.

Приложение find #

Документация #

Краткое описание принципа работы #

Данное приложение является классическим и поставляется во всех UNIX-системах. Его часто используют в качестве средства поиска данных.

Сводка об использовании:

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...] [expression]

Аргументы -H, -L, -P влияют на способ обработки символических ссылок, используются редко.

Если исключить их и опции по отладке, то ключевыми становятся следующие аргументы:

find [starting-point...] [expression]
  • Список каталогов, в которых происходит поиск. Если их не указать, то поиск будет проходить в текущем рабочем каталоге.
  • Выражение для поиска файлов. Если его не указать, то find будет считать все файлы подходящими и выведет пути к ним на стандартный поток вывода.

Подсчёт количества файлов в домашнем каталоге:

$ find ~ | wc -l
2399243

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

Проверки файлов #

  • -type по типам: обычные файлы, директории, ссылки, блоковые устройства. Например -type f поиск по обычным файлам.
  • -name по имени файла: можно указать шаблон в формате Bash. Например -name "*.jpg" для фильтрации всех файлов с расширением jpg.
  • -size по размеру файла: можно указать нижнюю и верхнюю границу. Например -size +50M для поиска файлов больше 50 мегабайт.
  • -cmin по времени модификации: можно указать точное время, верхнюю или нижнюю границу. Например -cmin -10 ограничивает время последними 10 минутами.
  • -cnewer file по времени модификации относительно другого файла. Вместо file надо указать путь к файлу.
  • -ctime по времени модификации за количество последних n суток.
  • -empty пустые файлы и каталоги.
  • -group по принадлежности к группе.
  • -iname по имени без учёта регистра.
  • -mmin по изменению содержимого за последние n минут.
  • -mtime по изменению содержимого за последние n суток.
  • -newer подходят файлы, модифицированные после указанного файла.
  • -nouser подходят файлы, которые относятся корректным пользователям.
  • -nogroup подходят файлы, которые относятся к некорректным группам.
  • -perm по атрибутам доступа.
  • -samefile поиск жёстких ссылок.
  • -user по имени пользователя.

Логические связи между проверками #

find позволяет указать логические связи между проверками. Поддерживаются следующие команды:

  • -and, -a логическое И. Обе проверки должны быть верными.
  • -or, -o логическое ИЛИ. Одна из проверок должна быть верной.
  • -not, ! логическое отрицание. Следующая за отрицанием проверка не должна пройти.
  • () группировка проверок. Проверка происходит слева направо.

Если связь явно не указана, то используется логическое И.

Пример поиска файлов, у которых права доступа не 0600, и каталогов, у которых права доступа не 0700, в домашнем каталоге:

$ find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \)

Для того, чтобы Bash не обрабатывал скобки, их необходимо экранировать.

Если выполненных проверок достаточно, чтобы выражение считалось верным, find не будет проводить дальнейшие. Т.е. логика совпадает с работой условных операторов в любых языках программирования.

Действия #

По умолчанию find просто выводит путь к найденному файлу на стандартный поток вывода. Однако find может выполнять и другие действия над найденными файлами.

  • -delete удалить файл.
  • -ls отобразить информацию о файле в широкой нотации.
  • -print вывести путь к файлу. Действие по умолчанию.
  • -quit выйти при нахождении первого подходящего файла.

Рассмотрим примеры.

Удалить все .bak файлы из домашней директории:

$ find ~ -type f -iname '*.bak' -delete

Отобразить все файлы:

$ find ~ -print -type f -name '*.bak'

-print стоит первым действием, поэтому исполняется для любого файла.

Пользовательские действия #

Помимо встроенных команд find позволяет также выполнить произвольную команду над найденным файлом. Для этого используется действие -exec:

-exec rm '{}' ';'

В этом случае для каждого найденного файла будет вызвана команда rm, которой вместо '{}' будет передан путь к файлу. Запуск rm будет происходить для каждого найденного файла. Без других фильтров данная команда удалит все найденные файлы.

Использование кавычек обусловлено тем, что фигурные скобочки и точка с запятой обрабатываются Bash самостоятельно.

Если вместо ';' указать +, то запуск приложения будет выполнен только 1 раз, а все найденные файлы будут переданы ему в качестве аргументов.

$ find ~ -type f -name 'foo*' -exec ls -l '{}' +

Задачи на использование find #

1. Базовые задачи на поиск #

  1. Найдите файл с названием test.txt в текущем рабочем каталоге.
  2. Найдите файл с названием unix.txt в каталоге /home.
  3. Найдите файл с названием linux.txt без учёта регистра в домашнем каталоге пользователя.
  4. Найдите каталог с названием user во всей файловой системе.
  5. Найдите в текущем рабочем каталоге файлы, заканчивающиеся расширением .sh.

2. Поиск по правам доступа #

  1. Найдите все обычные файлы с правами доступа 777 в текущем рабочем каталоге.
  2. Найдите все обычные файлы, у которых права доступа не равны 777 в корневом каталоге.
  3. Найдите все файлы, доступные на чтение владельцу во всей файловой системе.
  4. Найдите все файлы, доступные на исполнение всем пользователям во всей файловой системе.
  5. Найдите все обычные файлы с правами доступа 777 и исправьте их на права по умолчанию. Поиск производить в домашнем каталоге.
  6. Найдите все директории с правами доступа 777 и исправьте их на права по умолчанию. Поиск производите в домашнем каталоге пользователя.
  7. Найдите в текущем рабочем каталоге пользователя файл test.txt и удалите его с помощью встроенного действия.
  8. Выполните предыдущее задание с помощью вызова внешнего приложения.
  9. Найдите в домашнем каталоге пользователя все файлы с расширением mp3 и удалите их с помощью внешнего приложения.
  10. Решите предыдущую задачу, однако обеспечьте запуск внешнего приложения только один раз.
  11. Найдите все пустые файлы в каталоге /tmp.
  12. Найдите все пустые каталоги в каталоге /var/run.
  13. Найдите все скрытые файлы в каталоге /tmp.

3. Поиск с использованием владельца #

  1. Найдите во всей файловой системе файл fstab, принадлежащий пользователю root.
  2. Найдите все фалы, принадлежащие текущему пользователю, в каталоге /tmp.
  3. Найдите все директории, принадлежащие группе staff в каталоге /usr/local.
  4. Найдите все файлы с расширением txt, принадлежащие пользователю user, в каталоге /home.

4. Поиск файлов по времени изменения #

  1. Найдите файлы во всей файловой системе, которые были модифицированы 20 дней назад.
  2. Найдите файлы в домашнем каталоге пользователя, которые были изменены не ранее 10 дней назад и не позднее 5 дней назад.
  3. Найдите файлы в каталоге /tmp, которые были изменены за последний час.
  4. Найдите файлы в домашнем каталоге, к которым обращались в течение последнего часа.

5. Поиск файлов по размерам #

  1. Найдите файлы во всей файловой системе, размер которых составляет 1.5 мегабайта.
  2. Найдите файлы во всей файловой системе, размер которых варьируется от 2 до 15 мегабайт.
  3. Найдите файлы в домашнем каталоге, размер которых превышает 100 мегабайт и удалите их.
  4. Найдите файлы с расширением avi, размер которых превышает 700 мегабайт и удалите их, если пользователь согласиться на это действие.

Приложение fd #

Документация #

Установка в ALT Linux #

От имени суперпользователя выполните обновление репозиториев:

apt-get update

и установку приложения fd:

apt-get install fd

Задачи #

Выполните задачи для приложения find.

  • Смогли ли вы выполнить все действия с помощью fd-find?
  • Какая из программ выполняла поиск быстрее?
  • Сравните пользовательский интерфейс данных приложений друг с другом.

© A. M. Васильев, 2022, CC BY-SA 4.0, andrey@crafted.su