Рекурсивно искать директории по имени файла, остановиться при обнаружении.

Вопрос или проблема

У меня есть дерево каталогов, которое содержит файлы с одинаковыми именами, например:

a/file
a/...
a/b/file
x/a/file
x/a/...
x/b/file

Я пытаюсь использовать find-exec и -prune), чтобы получить все пути, где file встречается первым при рекурсивном поиске в дереве. Мой пример вернул бы:

a/file
x/a/file
x/b/file

Он не возвращает a/b/file, потому что файл с именем file уже находится в a/.

Как я могу этого добиться с помощью Bash?

find . -type d -exec sh -c '
   f="$1"/file
   [ -e "$f" ] && { printf "%s\n" "$f"; true; }
' find-sh {} \; -prune

Вместо того чтобы искать файлы, я ищу каталоги и проверяю наличие file в каждом каталоге. Если file существует, путь к нему выводится, и -prune активируется для каталога.

Примечания:

  • true используется, чтобы убедиться, что -prune выполняет свою работу, даже если printf завершится неудачей по какой-то причине.

  • В этом решении find никогда не обрабатывает файлы, он обрабатывает каталоги. Если вы хотите что-то сделать с file, вы можете сделать это из внутреннего шелла, используя $f.

    Пример: если бы я использовал … -prune -print, инструмент выведет путь к соответствующему каталогу, а не к файлу. Чтобы вывести путь к file, я использовал printf из внутреннего шелла.

С find, который знает нестандартный (но общедоступный) предикат -execdir для выполнения команды в родительском каталоге текущего пути:

$ find . -type d -execdir test -e file \; -prune -o -name file -print
./a/file
./x/b/file
./x/a/file

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

Ответ или решение

Рекурсивный Поиск Файлов По Имени: Как Остановить Спуск При Нахождении

В ситуации, когда у вас есть дерево директорий, которое содержит файлы с одинаковыми именами, задача поиска этих файлов становится более сложной. Рассмотрим решение, используя команду find в Bash, с возможностью остановки дальнейшего спуска по директориям, если файл с нужным именем уже найден.

Проблема

Вы имеете следующее дерево директорий:

a/file
a/b/file
x/a/file
x/b/file

При выполнении поиска файлы с именем file могут находиться в разных подкаталогах, но вам необходимо, чтобы поиск останавливался в подкаталогах, если файл уже найден в родительской директории. Результатом поиска должны стать пути к этим файлам:

a/file
x/a/file
x/b/file

Файл a/b/file не должен выводиться, так как file уже присутствует в директории a.

Решение

Используя команду find, можно реализовать такой подход. Команду следует запускать с ключом -exec, который позволит выполнять отдельный скрипт для каждой директории. Рассмотрим следующий пример:

find . -type d -exec sh -c '
   f="$1/file"
   [ -e "$f" ] && { printf "%s\n" "$f"; true; }
' sh {} \; -prune

Пояснение к скрипту

  1. Тип Поиска: -type d указывает на то, что мы ищем только директории.
  2. Выполнение Скрипта: -exec sh -c '...' позволяет выполнять оболочку для каждой директории, передавая путь как $1.
  3. Проверка Файла: Внутри оболочки мы создаем переменную f, в которую помещаем полный путь к файлу с именем file.
  4. Условие Существования: Команда [ -e "$f" ] проверяет, существует ли файл. Если файл найден, мы выводим его путь с помощью printf.
  5. Прекращение Спуска: Команда true позволяет -prune корректно завершить процесс.

Альтернативный Подход

Существует и другой способ реализации данной задачи с использованием предиката -execdir, который позволяет выполнять команды в родительской директории текущего пути:

find . -type d -execdir test -e file \; -prune -o -name file -print

Описание Альтернативного Подхода

  1. Тип Поиска: Аналогично предыдущему, мы ищем только директории.
  2. Проверка Наличия Файла: Если file существует в директории, она будет обрезана с помощью -prune, и дальнейший поиск продолжаться не будет.
  3. Вывод Нужных Файлов: Если элемент не является директорией и носит имя file, его путь будет напечатан.

Заключение

Использование командной строки для поиска файлов с одинаковыми именами, с остановкой на уровне директории, — это эффективный способ управления файлами и каталогами в Unix-подобных системах. Решение, представленное выше, позволит вам просто и быстро находить нужные файлы в сложных структурах директорий, значительно упрощая процесс их организации и учета.

Оцените материал
Добавить комментарий

Капча загружается...