Я пытаюсь разработать команду, которая рекурсивно находит каталоги, содержащие только один или несколько каталогов на одном уровне. Предпочтительно с помощью команды find
. Например find . -type d
.
Например, в следующей структуре файла:
/tmp/folder1/folder1a/test.jpg
/tmp/folder1/file1a.tmp
/tmp/folder2/folder2a/test.jpg
/tmp/folder3/folder3a/
/tmp/folder3/folder3b/file.jpg
Я хотел бы остановиться на нем, folder2
поскольку folder3
он сам по себе не содержит файлов, а содержит только папки (с файлами).
решение1
comm -23 <(find . -type d ! -empty | sort -u) <(find . -type f -printf '%h\n' | sort -u)
Это список непустых папок (по крайней мере, одна вещь в нем), исключая те, которые содержат какие-либо файлы. Если вы также хотите исключить такие вещи, как каналы и символические ссылки, вы можете использовать ! -type d
вместо -type f
. Это нельзя сделать в одном операторе find, потому что find не может соответствовать сложным критериям содержимого (это не XPath).
решение2
Если я правильно понял, то это должно сработать:
find . -type d ! -empty -exec sh -c '\
[ -z "`find "$1" -maxdepth 1 -mindepth 1 ! -type d -print -quit`" ]\
' sh {} \; -print
Из-за -empty
, -maxdepth
, -mindepth
и -quit
, которые отсутствуют в POSIX, решение может не работать в вашей ОС ( -print -quit
только для ускорения процесса, вы можете опустить этот фрагмент, -maxdepth 1 -mindepth 1
хотя он важен).
Хитрость заключается в запуске отдельной оболочки для каждого непустого каталога, которая проверяет (не рекурсивно), не содержит ли каталог ничего, что не является каталогом. Это делается с помощью -exec sh … \;
, здесь это действует как тест. Если каталог не содержит ничего, что не является каталогом, то вывод внутреннего кода find
пуст, поэтому тест ( [ -z … ]
) возвращает статус выхода 0
, sh
возвращает 0
, -exec
является истинным.