
Я хочу найти файлы из трех разных папок, включая и исключая определенные файлы.
Папка 1:
- Путь: /var/www/app/var/log/
- Исключить только: file1.log и file2.log
Папка 2:
- Путь: /var/log/web/log/
- Включить только: error.log
Папка 3:
- Путь: /var/log/service/log/
- Включить только: app1.error.log и app2.error.log
Как в этом случае искать файлы из трех разных папок?
решение1
Вы можете сделать это с помощью find
. Прочитайте об общем использовании find
в контексте исключения и включения:Рекурсивный поиск файлов с исключениями и включениями.
Ваша проблема включает три пути и различные требования для каждого. Можно указать много начальных точек в одном вызове find
и построить выражение (например, с -path
), чтобы для разных путей выполнялись разные тесты. Это возможно, но довольно громоздко. Простой способ — запустить три отдельные команды find последовательно.
find /var/www/app/var/log ! -name file1.log ! -name file2.log
find /var/log/web/log -name error.log
find /var/log/service/log -name app1.error.log -o -name app2.error.log
Примечания:
Несколько пробелов в приведенных выше командах нужны только для того, чтобы подчеркнуть их структуру и сходство.
Вы говорите: «Я хочу найти файлы». Вышеуказанные команды найдутфайлывключая файлы типа каталог; в частности, первая команда найдет свою собственную начальную точку (
…/log
). Чтобы найти только обычные файлы, вам нужно-type f
. Чтобы найти только некаталоги, вам нужно! -type d
.Если
file1.log
илиapp1.error.log
относится к типу каталога, то неясно, относится ли "включено" или "исключено" к каталогу в отдельности или к каталогу и всему, что находится ниже. Это, вероятно, не проблема, поскольку, скорее всего,file1.log
и такие файлы являются обычными файлами в вашей настройке.Для справки, каждая из приведенных выше команд проходит по всему дереву каталогов под своей начальной точкой. Например, если
file1.log
имеет тип directory, то! -name file1.log
не остановитсяfind
на тестированииfile1.log/foo
. Чтобы исключить поддерево, вам нужно-prune
.find
работает рекурсивно. Самый простой способ заставить GNUfind
не спускаться в подкаталоги —-maxdepth 1
. Реализации, отличные от GNU, могут не поддерживать это. С чисто POSIXfind
это не так просто.Вы отметилиубунту; Ubuntu предоставляет GNU
find
из коробки, поэтому пользуйтесь им-maxdepth 1
свободно.Правильное использование
-o
не так просто, как вам бы хотелось.Если задействованы символические ссылки, прочтите о параметрах
-H
и в . Возможно, вы захотите использовать один из них.-L
man 1 find
Учитывая все это, я могу создать пример варианта третьей команды, котораяможет бытьлучше соответствует вашим потребностям:
find /var/log/service/log/ -maxdepth 1 -type f \( -name app1.error.log -o -name app2.error.log \)
Или в стиле POSIX (чтобы сделать ответ более полезным для широкой аудитории):
find /var/log/service/log/. \( -name . -o -prune \) -type f \( -name app1.error.log -o -name app2.error.log \)
Последний компонент начальной точки в последней команде заканчивается на .
. Это позволяет нам использовать универсальное решение (я имею в виду, что форма -name . -o -prune
не зависит от действительно значимой части пути начальной точки). С другой стороны, find
будет включать /.
в каждое имя пути, вам это может не понадобиться.
Выполнение трех find
s вместо одного не мешает вам передавать результаты в один пункт назначения (например, xargs
):
{ find … ; find … ; find … ; } | xargs …
Обратите внимание, в Ubuntu вы можете сделать find … -print0 | xargs -r0 …
. Этоболее прочныйчем find … -print | xargs …
, хотя и не переносимый.