ツリー内のすべての終了サブディレクトリを探します。

ツリー内のすべての終了サブディレクトリを探します。

次の構造を考えると:

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番目の項目です。サブディレクトリがある場合、各サブディレクトリには親ディレクトリへの..というハードリンクもあります。これ。および..ディレクトリエントリは通常、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を使用せずに...)
  • すべてのファイルシステムで動作しますか?

答え1

より明確なオプションがあります-empty

find . -type d -empty

直す。まあ、あなたは正しいです。この方法はディレクトリ内のファイルには機能しません。

したがって、固定ファイルシステムの信頼できないバージョンは次のとおりです。

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

答え2

あなたのソリューションを補うために、-linksUnixディレクトリ接続ルールに従わないファイルシステムでは機能しないことを付け加えたいと思います。man findオプションを見ると、-noleaf少なくともCD-ROM、MS-DOSファイルシステム、およびAFSボリュームのマウントポイントがあります。

参考までに、この問題は実際にはより遅く、通常はsed / awkと同様のパイプに依存するさまざまなソリューションで議論されています。

答え3

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 }
'

答え4

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

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

その方法は次のようになります。緊急解決しかし、パイプはありません。

関連情報