найти все конечные подкаталоги в дереве

учитывая следующую структуру:

oz123@debian:~/ $ tree . . ├── a │ ├── a1 │ ├── a2 │ └── a3 ├── a1 │ ├── a11 │ ├── a12 │ └── a31 ├── b │ └── b1 │ ├── b11 │ │ └── b21 │ │ └── b31 │ ├── b12 │ └── b3 └── c 16 directories, 0 files 

Как найти все конечные узлы?

Я нашел следующие решения, которые кажутся хорошими, но я должен доказать, что нет тестового примера, который не даст этого.

Страница справки в -links :

Вы также можете искать файлы с определенным количеством ссылок с помощью «-links». Обычно в каталогах есть как минимум две жесткие ссылки; их. вход второй. Если у них есть подкаталоги, каждый из них также имеет жесткую ссылку, которая называется .. в ее родительский каталог. . и .. записи в каталоге обычно не просматриваются, если они не указаны в командной строке поиска.

возможное решение:

 oz123@debian:~/ $ find . -type d -links 2 ./a/a2 ./a/a3 ./a/a1 ./c ./a1/a31 ./a1/a11 ./a1/a12 ./b/b1/b12 ./b/b1/b3 ./b/b1/b11/b21/b31 
  • Может ли кто-нибудь обеспечить лучшее решение (без использования труб и sed, это было бы …)
  • Будет ли он работать с любой файловой системой?

  • Сжатие tar-файла без извлечения содержимого
  • установка разрешений по умолчанию с помощью setfacl
  • Почему в директориях / dev для каталогов, например pts?
  • Как узнать, какие программы читают мой файл?
  • это linux: все ли файл снижает производительность?
  • Переход в последний измененный подкаталог текущего каталога
  • Могут ли каталоги и файлы наследовать те же разрешения, что и родительский каталог?
  • Добавить человекообразную метку времени последнего редактирования в имя файла
  • 4 Solutions collect form web for “найти все конечные подкаталоги в дереве”

    В дополнение к вашему собственному решению с помощью -links , я хочу просто добавить, что он не будет работать на файловых системах, которые не следуют соглашению об установке ссылок на Unix. Из man find on option -noleaf это, по крайней мере, CD-ROM, файловые системы MS-DOS и точки монтирования тома AFS.

    Для справки этот вопрос уже обсуждался с различными решениями, которые действительно медленнее и обычно прибегают к трубопроводу к sed / awk и тому подобному.

    Существует несколько более очевидный вариант:

     find . -type d -empty 

    UPD. Хорошо, вы правы таким образом, не будет работать с файлами в каталогах.

    Таким образом, это фиксированная файловая система, не зависящая от версии:

     find dtest/ -type d -exec sh -c "if [ \$(find {} -maxdepth 1 -type d | wc -l) -eq 1 ]; then echo {} ; fi" \; 

    find . -type d -links 2 find . -type d -links 2 работает на большинстве файловых систем, но не на всех. Я не думаю, что есть способ узнать, кроме как узнать, какие типы файловой системы имеют свойство, что каталоги содержат ссылку на себя. Поиск GNU обнаруживает это динамически (если он печатает что-то о «Автоматическом включении опции -noleaf от find», вы знаете, что ваша файловая система не обладает этим свойством). Наиболее распространенные типы файловой системы – это нормально, но не FAT или btrfs.

    Если вы хотите быть уверенным, вам придется протестировать каждый каталог. Один из способов сделать это – снова вызвать find для каждого подкаталога.

     find . -type d ! -exec sh -c ' find "$1/." ! -name . -type d -prune | grep -q "^"' sh {} \; -print 

    (с помощью GNU find вы можете заменить -prune на -print -quit чтобы сделать его более эффективным).

    Другим способом является пост-обработка вывода find . С помощью find -depth каталог листьев – это тот, который не соответствует самому подкаталогу.

     find . -depth -type d -print0 | awk -v RS='\0' ' substr(previous, 1, length($0) + 1) != $0 "/" { previous = $0 } ' 

    Попробуйте следующее решение (должно быть совместимо с Linux, Unix и OS X):

     find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' ';' 

    Это аналогичный подход к быстрому решению , но без каких-либо труб.

    Linux и Unix - лучшая ОС в мире.