Как вывести список всех файлов, но только в тех каталогах, в которых нет подкаталогов?

Как вывести список всех файлов, но только в тех каталогах, в которых нет подкаталогов?

У меня есть дерево каталогов, в котором я хочу выполнить рекурсивный поиск всех файлов определенного типа (например, всех .jpgфайлов ), но я хочу вывести список этих файлов только в том случае, если они находятся в самом низу дерева каталогов.

Например, если мое дерево выглядит так:

                          home
                          root
                   f1     f2     f3
                   f11    f22    f33
                   f111   f222   f333

и все папки содержат .jpg', я хочу перечислить только .jpg' в f111/ f222/ f333и т. д. и игнорировать те, что находятся в папках выше.

Я знаю, что могу использовать команду find (например, find . -name "*.jpg"), чтобы получить список всех .jpgпапок во всем дереве, но я не уверен, как ограничить его только самыми нижними папками, не прибегая к grepфильтрации результатов по символам 111/ 222/ 333, что на самом деле невыполнимо, поскольку у меня сотни папок, и я не знаю, как могут называться папки последнего уровня для каждой из них по отдельности.

решение1

Это можно сделать в два этапа:

find . -type d -links 2 -print0 | xargs -0 -I{} find {} -name \*.jpg

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

решение2

Эквивалент POSIXРешение @TomHunt.

find . -type d -links 2 -exec sh -c '
  find "$@" -type f -name "*.jpg"' sh {} +

Полагается -links 2на свойство некоторых файловых систем, что количество ссылок каталогов (изначально 2 для записи в их родителе и записи .в них самих) увеличивается на единицу для каждого подкаталога (из-за ..записи в них). Некоторые современные файловые системы, такие как btrfsили nilfs, чьи структуры радикально отличаются, не имеют такого свойства.

С помощью zshможно сделать что-то вроде:

has_subdirs() {
  local l
  l=($REPLY/*(/DNoN[1]))
  (($#l))
}
dirs_without_subdirs=(**/*(DN^+has_subdirs))
jpgs=($^dirs_without_subdirs/*.jpg(ND.))
(($#jpgs)) && printf '%s\n' $jpgs

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