Linuxに、ブランチの終わり(ここではそれらをリーフと呼びます)、つまりサブディレクトリのないディレクトリだけのディレクトリツリーを調べる方法はありますか?私は この質問 を見ましたが、適切に回答されていませんでした。
だから私がディレクトリツリーを持っているなら
root/
├── branch1
│ ├── branch11
│ │ └── branch111 *
│ └── branch12 *
└── branch2
├── branch21 *
└── branch22
└── branch221 *
ブランチの終わりにあるディレクトリ(*
)、それでファイルの数ではなく、ディレクトリの数だけを見ますか?私の実際のケースでは、ファイルのあるものを探していますが、これらは、この例で見つけたい「葉」のサブセットです。
ファイルが含まれているリーフディレクトリのみを検索するには、参照されている質問 https://unix.stackexchange.com/a/203991/330217 または類似の質問 https:の回答を組み合わせることができます。 //stackoverflow.com/a/4269862/10622916 または https://serverfault.com/a/530328 with find
's ! -empty
find rootdir -type d -links 2 ! -empty
-links 2
を使用したハードリンクのチェックは、従来のUNIXファイルシステムで機能するはずです。 -empty
条件はPOSIX標準の一部ではありませんが、ほとんどのLinuxシステムで使用できるはずです。
KamilMaciorowskiのコメントによると、ディレクトリの従来のリンク数セマンティクスはBtrfsでは無効です。これは https://linux-btrfs.vger.kernel.narkive.com/oAoDX89D/btrfs-st-nlink-for-directories で確認されており、従来の例外としてMac OS HFS +について言及しています動作。これらのファイルシステムでは、リーフディレクトリをチェックするために別の方法が必要です。
ネストされたfind
を使用して、サブディレクトリの数を数えることができます:
find . -type d \
\( -exec sh -c 'find "$1" -mindepth 1 -maxdepth 1 -type d -print0 | grep -cz "^" >/dev/null 2>&1' _ {} \; -o -print \)
*/
ファイル名展開パターンがディレクトリの名前ではないものに展開されると、現在のディレクトリには(非表示ではない)サブディレクトリがありません。
find
の場合:
find root -type d -exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; ! -empty -print
これは、パターンがシンボリックリンクを通過するため、リーフディレクトリ内のディレクトリへのシンボリックリンクをディレクトリとして扱うことに注意してください。
-empty
述語は標準ではありませんが、しばしば実装されます。それがなければ、サブディレクトリを検出するのと同じようなことをするでしょう:
find root -type d \
-exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; \
-exec sh -c 'set -- "$1"/*; [ -e "$1" ]' sh {} \; -print
または、もう少し効率的に、
find root -type d -exec sh -c '
dir=$1
set -- "$dir"/*/
[ -d "$1" ] && exit 1
set -- "$dir"/*
[ -e "$1" ]' sh {} \; -print
または、-links
忘れていた述語( thanks Bodo ):
find root -type d \
-links 2 \
-exec sh -c 'set -- "$1"/*; [ -e "$1" ]' sh {} \; -print
zsh
の場合:
leafdirs=(**/*(ND/Fl2))
一致するリーフディレクトリのリストを$leafdirs
配列に設定します。
あなたはそれを1行に1つ印刷できます:
printf '%s\n' $leafdirs
または、次のようにループします:
for dir ($leafdirs) something with $dir
これは多かれ少なかれ @ BodoのGNU find
answer の翻訳なので、実際のディレクトリエントリとしてext4
と.
を実装する..
などの従来のUnix風のファイルシステムでのみ機能します。
**/
:任意のレベルのサブディレクトリ(NF/Fl2)
:グロブ修飾子N
:その1つのグロブに対してnullglob
を有効にします。一致がない場合でも失敗しません。代わりに、結果は空のリストになりますD
:その1つのグロブに対してdotglob
を有効にします。隠しディレクトリ内を調べ、隠しファイルをスキップしません/
:タイプディレクトリのみのファイルを選択(-type d
など)F
:selectfullディレクトリ:.
および..
以外の少なくとも1つのエントリを含むディレクトリ(GNU find
の! -empty
など)l2
:リンク数が2のdirsのみ(-links 2
など)。 1つは親ディレクトリのdirのエントリ用で、もう1つはその中の.
用です。これらの..
エントリのため、サブディレクトリはリンクカウントに1を追加します。