次のファイルシステム構造を想定します。
ROOT
DIR1A
FILE
DIR2A
DIR2B
DIR3A
DIR1B
DIR2C
DIR2D
DIR3B
DIR1C
DIR2E
FILE
任意のディレクトリから始めて、空のサブディレクトリを一覧表示せずにa)何も含まない、またはb)空のディレクトリのみを含む最も浅いサブディレクトリのみを一覧表示するにはどうすればよいですか?
つまり、上記の場合、ROOTで始まると次のようになります。
- DIR1A にはファイルが含まれているため、リストされません。
- DIR2Aには何も含まれていないため、リストされています。
- DIR2Bには空のディレクトリのみが含まれているため、一覧表示されます。
- DIR3A はすでにリストされている浅いディレクトリにあるため、リストされません。
- DIR1Bには空のディレクトリのみが含まれているため、一覧表示されます。
- DIR1B のサブディレクトリは、すでにリストされている浅いディレクトリにあるため、リストされません。
- DIR1CまたはDIR2Eにはファイルがネストされているため、リストされません。
私はこれを表現するより効率的な方法があると思います。たぶん、「何も含まれていないか、空のディレクトリだけを含む最上位のディレクトリだけをリストしたいですか?」
編集:上記の言語の一部を明確にしようとしました。
答え1
ディレクトリツリーをあまり探索しないで実行されるコマンドの数を最小限に抑えるには、次のようにします(GNUfind
およびsort
同様のNULをエコー区切り文字awk
としてサポートしていると仮定)。R
S
find . -type d -print0 -o -printf 'f/%h\0' |
LC_ALL=C sort -zru |
LC_ALL=C awk -F/ -vRS='\0' '
function parent(path) {
sub("/[^/]*$", "", path)
return path
}
$1 == "f" {
sep = path = ""
for (i = 2; i <= NF; i++) {
black[path = path sep $i]
sep = FS
}
next
}
! ($0 in black) && ($0 == "." || parent($0) in black)'
その下にディレクトリ以外のファイルを含むすべてのディレクトリを黒で塗りつぶし、黒の親を持つ(または特別な場合は親を持たない)黒ではない.
ディレクトリを印刷します。
これらのディレクトリを削除することが目標である場合は、次のようにできます。
find . -depth -type d -empty -delete
-delete
を意味します-depth
が、明確にするためにここに追加します(GNUのfind
マニュアルで提案されているように)。-delete
いずれにせよ、空のディレクトリのみが削除されるため、空で-empty
ないディレクトリを削除できないときに発生するエラーメッセージを回避できます。深さ優先を使用するd
と、ディレクトリ以外のファイルを除く構造全体を削除し、葉がある分岐前の葉を削除します。
-delete
BSDとGNUの非標準的な拡張ですが、-empty
どちらも現在かなり一般的です。そのエントリがない場合は、いつでも次の2つを置き換えることができます(おそらく次のエラーメッセージを削除できます)。-delete
-empty
find
find
-exec rmdir {} +
2> /dev/null
みんなfind
と)エラーメッセージrmdir
。
答え2
遅れてそうです。
find -type d -exec sh -c '[ -z "$(find "$@" -type f -print -quit)" ]' _ {} \; -print -prune
はい
# Setup your configuration
mkdir -p root/{dir1a/{dir2a,dir2b/dir3b},dir1b/{dir2c,dir2d/dir3b},dir1c/dir2e}
touch root/{dir1a,dir1c/dir2e}/file
# Run the finder
find root -type d -exec sh -c '[ -z "$(find "$@" -type f -print -quit)" ]' _ {} \; -print -prune
# Output
root/dir1b
root/dir1a/dir2b
root/dir1a/dir2a
説明する
サブシェルは各ディレクトリに対して順番に呼び出されexec
、一番上から始めて下に(つまり幅優先)作業されます。現在位置からファイルを検索し、ファイルtrue
が存在しない場合に返します。 main はfind
それから状態結果を取得し、成功するexec
と現在のディレクトリを印刷し、残りのサブツリー検索を停止します。