Untuk menemukan hanya direktori daun yang berisi file, Anda dapat menggabungkan jawaban dari pertanyaan yang direferensikan https://unix.stackexchange.com/a/203991/330217 atau pertanyaan serupa https://stackoverflow.com/a/4269862/10622916 atau https://serverfault.com/a/530328 dengan find
! -empty
find rootdir -type d -links 2 ! -empty
Memeriksa tautan keras dengan -links 2
harus bekerja untuk sistem file UNIX tradisional. -empty
condition bukan bagian dari standar POSIX, tetapi seharusnya tersedia di sebagian besar sistem Linux.
Menurut komentar KamilMaciorowski, semantik penghitungan tautan tradisional untuk direktori tidak valid untuk Btrfs. Ini dikonfirmasi di https://linux-btrfs.vger.kernel.narkive.com/oAoDX89D/btrfs-st-nlink-for-directories yang juga menyebutkan Mac OS HFS+ sebagai pengecualian dari perilaku tradisional. Untuk sistem file ini diperlukan metode yang berbeda untuk memeriksa direktori daun.
Anda dapat menggunakan find
bersarang dan hitung jumlah subdirektori:
find . -type d \
\( -exec sh -c 'find "$1" -mindepth 1 -maxdepth 1 -type d -print0 | grep -cz "^" >/dev/null 2>&1' _ {} \; -o -print \)
Jika */
pola globbing nama file memperluas ke sesuatu yang bukan nama direktori, maka direktori saat ini tidak memiliki subdirektori (tidak tersembunyi).
Dengan find
:
find root -type d -exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; ! -empty -print
Perhatikan bahwa ini akan memperlakukan tautan simbolik ke direktori di direktori daun sebagai direktori karena polanya akan melewati tautan simbolik.
-empty
predikat tidak standar, tetapi sering diterapkan. Tanpa itu, Anda akan melakukan sesuatu yang mirip dengan mendeteksi subdirektori:
find root -type d \
-exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; \
-exec sh -c 'set -- "$1"/*; [ -e "$1" ]' sh {} \; -print
Atau, sedikit lebih efisien,
find root -type d -exec sh -c '
dir=$1
set -- "$dir"/*/
[ -d "$1" ] && exit 1
set -- "$dir"/*
[ -e "$1" ]' sh {} \; -print
Atau, gunakan -links
predikat yang sudah saya lupakan (terima kasih Bodo):
find root -type d \
-links 2 \
-exec sh -c 'set -- "$1"/*; [ -e "$1" ]' sh {} \; -print