Найти файлы из разных каталогов с включением и исключением некоторых

Найти файлы из разных каталогов с включением и исключением некоторых

Я хочу найти файлы из трех разных папок, включая и исключая определенные файлы.
Папка 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работает рекурсивно. Самый простой способ заставить GNU findне спускаться в подкаталоги — -maxdepth 1. Реализации, отличные от GNU, могут не поддерживать это. С чисто POSIXfind это не так просто.

    Вы отметили; Ubuntu предоставляет GNU findиз коробки, поэтому пользуйтесь им -maxdepth 1свободно.

  • Правильное использование-o не так просто, как вам бы хотелось.

  • Если задействованы символические ссылки, прочтите о параметрах -Hи в . Возможно, вы захотите использовать один из них.-Lman 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будет включать /.в каждое имя пути, вам это может не понадобиться.


Выполнение трех finds вместо одного не мешает вам передавать результаты в один пункт назначения (например, xargs):

{ find … ; find … ; find … ; } | xargs …

Обратите внимание, в Ubuntu вы можете сделать find … -print0 | xargs -r0 …. Этоболее прочныйчем find … -print | xargs …, хотя и не переносимый.

Связанный контент