ツリー内のすべての終了サブディレクトリを見つける


11

次の構造が与えられた場合:

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」を使用して、特定の数のリンクを持つファイルを検索することもできます。通常、ディレクトリには少なくとも2つのハードリンクがあります。彼らの。エントリは2番目のものです。サブディレクトリがある場合、それぞれに親ディレクトリへの..というハードリンクもあります。。および..ディレクトリエントリは、findコマンドラインで言及されていない限り、通常は検索されません。

可能な解決策:

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を使用せずに、これはパフォーマンスが向上しています...)
  • どのファイルシステムでも動作しますか?

3
あなたは-links 2トリック以上のパフォーマンスを見つけることはありません。動作しません btrfs
ステファンシャゼル

回答:


3

を使用した独自のソリューションへの追加として、-linksUnixのディレクトリリンク規則に従っていないファイルシステムでは機能しないことを付け加えます。man findオプションから、-noleafこれらは少なくともCD-ROM、MS-DOSファイルシステム、およびAFSボリュームマウントポイントです。

参考までに、この質問は、実際にはより遅く、通常はsed / awkなどのパイピングに頼るさまざまなソリューションで既に議論されています。


3

もう少し明白なオプションがあります-empty

find . -type d -empty

更新しました。わかりました、この方法はdirsのファイルでは動作しません。

したがって、ここでは、ファイルシステムの依存しない固定バージョンです。

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

2
質問を理解すると、エンドディレクトリにファイルが含まれる場合があります。「空」にならないため、これらのディレクトリは印刷されません
Stefan

@ラッシュ、サブディレクトリは空であってもなくても
かまい

@ Oz123は私の更新を確認してください、それは十分に速いはずですが、あなたの方法に比べて少し遅くなります。
ラッシュ

@rush、ありがとう、しかし、私は本当にパイプを避ける必要があります、彼らは物事を遅くすることができます。
Oz123

1

find . -type d -links 2ほとんどのファイルシステムで動作しますが、すべてではありません。ディレクトリに自分自身へのリンクが含まれているというプロパティがあるファイルシステムのタイプを知ること以外に知る方法はないと思います。GNU findはこれを動的に検出します(「findの-noleafオプションを自動的に有効にする」ことについて何かを出力する場合、ファイルシステムにこのプロパティがないことがわかります)。最も一般的なファイルシステムの種類は問題ありませんが、FATやbtrfsは問題ありません。

確認したい場合は、各ディレクトリをテストする必要があります。これを行う1つの方法は、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 }
'

0

次の解決策を試してください(Linux、Unix、およびOS Xと互換性があります)。

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

ラッシュソリューションと同様のアプローチですが、パイプはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.