Вопрос или проблема
У меня есть дерево каталогов, которое содержит файлы с одинаковыми именами, например:
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
Пояснение к скрипту
- Тип Поиска:
-type d
указывает на то, что мы ищем только директории. - Выполнение Скрипта:
-exec sh -c '...'
позволяет выполнять оболочку для каждой директории, передавая путь как$1
. - Проверка Файла: Внутри оболочки мы создаем переменную
f
, в которую помещаем полный путь к файлу с именемfile
. - Условие Существования: Команда
[ -e "$f" ]
проверяет, существует ли файл. Если файл найден, мы выводим его путь с помощьюprintf
. - Прекращение Спуска: Команда
true
позволяет-prune
корректно завершить процесс.
Альтернативный Подход
Существует и другой способ реализации данной задачи с использованием предиката -execdir
, который позволяет выполнять команды в родительской директории текущего пути:
find . -type d -execdir test -e file \; -prune -o -name file -print
Описание Альтернативного Подхода
- Тип Поиска: Аналогично предыдущему, мы ищем только директории.
- Проверка Наличия Файла: Если
file
существует в директории, она будет обрезана с помощью-prune
, и дальнейший поиск продолжаться не будет. - Вывод Нужных Файлов: Если элемент не является директорией и носит имя
file
, его путь будет напечатан.
Заключение
Использование командной строки для поиска файлов с одинаковыми именами, с остановкой на уровне директории, — это эффективный способ управления файлами и каталогами в Unix-подобных системах. Решение, представленное выше, позволит вам просто и быстро находить нужные файлы в сложных структурах директорий, значительно упрощая процесс их организации и учета.