Chcete-li najít pouze ty listové adresáře, které obsahují soubory, můžete zkombinovat odpověď na odkazovanou otázku https://unix.stackexchange.com/a/203991/330217 nebo podobné otázky https://stackoverflow.com/a/4269862/10622916 nebo https://serverfault.com/a/530328 s find
's ! -empty
find rootdir -type d -links 2 ! -empty
Kontrola pevných odkazů pomocí -links 2
by měl fungovat pro tradiční souborové systémy UNIX. -empty
stav není součástí standardu POSIX, ale měl by být dostupný na většině systémů Linux.
Podle komentáře KamilMaciorowského neplatí tradiční sémantika počtu odkazů pro adresáře pro Btrfs. To je potvrzeno v https://linux-btrfs.vger.kernel.narkive.com/oAoDX89D/btrfs-st-nlink-for-directories, kde je také zmíněn Mac OS HFS+ jako výjimka z tradičního chování. Pro tyto systémy souborů je nutná jiná metoda pro kontrolu listových adresářů.
Můžete použít vnořený find
a spočítat počet podadresářů:
find . -type d \
\( -exec sh -c 'find "$1" -mindepth 1 -maxdepth 1 -type d -print0 | grep -cz "^" >/dev/null 2>&1' _ {} \; -o -print \)
Pokud */
vzor globbingu názvu souboru se rozšíří na něco, co není názvem adresáře, pak aktuální adresář nemá žádné (neskryté) podadresáře.
S find
:
find root -type d -exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; ! -empty -print
Všimněte si, že toto by považovalo symbolický odkaz na adresář v listovém adresáři za adresář, protože vzor by přešel přes symbolický odkaz.
-empty
predikát není standardní, ale často implementovaný. Bez něj byste udělali něco podobného jako s detekcí podadresářů:
find root -type d \
-exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; \
-exec sh -c 'set -- "$1"/*; [ -e "$1" ]' sh {} \; -print
Nebo o něco efektivněji
find root -type d -exec sh -c '
dir=$1
set -- "$dir"/*/
[ -d "$1" ] && exit 1
set -- "$dir"/*
[ -e "$1" ]' sh {} \; -print
Nebo pomocí -links
predikát, na který jsem zapomněl (díky Bodo):
find root -type d \
-links 2 \
-exec sh -c 'set -- "$1"/*; [ -e "$1" ]' sh {} \; -print