web-dev-qa-db-ja.com

サブツリーのすべての空のディレクトリを削除するにはどうすればよいですか?

サブツリーの空のディレクトリをすべて削除するにはどうすればよいですか?私はのようなものを使いました

find . -type d -exec rmdir {} 2>/dev/null \;

しかし、空のディレクトリのみを含むディレクトリを削除するには、複数回実行する必要があります。さらに、それは特にcygwinの下ではかなり遅いです。

159
maaartinus

GNU findオプションと述語を組み合わせると、このコマンドは次のように機能します。

find . -type d -empty -delete
  • -type dはディレクトリに制限されます
  • -emptyは空のものに制限されています
  • -deleteは各ディレクトリを削除します

ツリーは-depthに含まれているため、-deleteを指定する必要なしに、葉からウォークされます。

深くネストされたディレクトリを最初にリストします。

find . -depth -type d -exec rmdir {} \; 2>/dev/null

(リダイレクトはfindだけでなくrmdirコマンド全体に適用されることに注意してください。rmdirのみにリダイレクトすると、中間シェル)

空でないディレクトリでrmdirを実行しないようにするには、-empty検索する述語。 GNU findは、コマンドを実行しようとしているときにディレクトリをテストするため、空になったばかりのディレクトリが取得されます。

find . -depth -type d -empty -exec rmdir {} \;

速度を上げる別の方法は、rmdir呼び出しをグループ化することです。特にCygwinでは、どちらもオリジナルよりも著しく高速になる可能性があります。私はこれらの2つの間に大きな違いを期待しません。

find . -depth -type d -print0 | xargs -0 rmdir 2>/dev/null
find . -depth -type d -exec rmdir {} + 2>/dev/null

どちらの方法が速いかは、空でないディレクトリの数によって異なります。結合することはできません-empty呼び出しをグループ化するためのメソッドを使用します。空のディレクトリのみを含むディレクトリは、findがそれらを参照する時点では空ではないためです。

別の方法は、複数のパスを実行することです。これが速いかどうかは、findの実行間でディレクトリ階層全体をディスクキャッシュに残せるかどうかなど、多くのことに依存します。

while [ -n "$(find . -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done

または、zshを使用します。 glob qualifierFは空でないディレクトリに一致するため、/^Fは空のディレクトリに一致します。空のディレクトリのみを含むディレクトリは、それほど簡単に照合することはできません。

while rmdir **/*(/N^F); do :; done

(これは、rmdirが空のコマンドラインを受け取ると終了します。)

rmdir-pを追加するだけで、1回のパスで機​​能します。それはかなりまたは最適ではありませんが、すべてを取得する必要があります。これは、削除するディレクトリの空でない親ディレクトリを削除するようにrmdirに指示します。

-emptyテストを追加して検索を少し節約できるので、空でないディレクトリを使用する必要はありません。

6
mattdm

find . -depth -type d -exec rmdir {} +

この質問に対する最も簡単で標準に準拠した答えです。

ここに記載されている他の回答は、残念ながらすべてのシステムに存在しないベンダー固有の拡張機能に依存しています。

3
schily

特にdupegurを使用してディスク領域をクリーンアップする場合は特に、頻繁に使用されるfindコマンドにこれらのエイリアスを使用します。重複を削除すると、多くの空のディレクトリが生じる可能性があります。

コメントは.bashrc内にあるので、後で微調整する必要があるときに忘れないようにします。

# find empty directories
alias find-empty='find . -type d -empty'

# fine empty/zero sized files
alias find-zero='find . -type f -empty'

# delete all empty directories!
alias find-empty-delete='find-empty -delete'

# delete empty directories when `-delete` option is not available.
# output null character (instead of newline) as separator. used together
# with `xargs -0`, will handle filenames with spaces and special chars.
alias find-empty-delete2='find-empty -print0 | xargs -0 rmdir -p'

# alternative version using `-exec` with `+`, similar to xargs.
# {}: path of current file
# +: {} is replaced with as many pathnames as possible for each invocation.
alias find-empty-delete3='find-empty -exec rmdir -p {} +'

# for removing zero sized files, we can't de-dupe them automatically
# since they are technically all the same, so they are typically left
# beind. this removes them if needed.
alias  find-zero-delete='find-zero -delete'
alias find-zero-delete2='find-zero -print0 | xargs -0 rm'
alias find-zero-delete3='find-zero -exec rm {} +'
0
raychi

find . -type d -printf "%d %p\n" |\ sort -nr |\ Perl -pe 's/^\d+\s//;' |\ while read dir; do \ (rmdir "$dir" > /dev/null 2>&1); \ done

仕組みは次のとおりです。

  1. すべてのディレクトリとその深さを再帰的にリストします
  2. 深さの降順で並べ替え
  3. ディレクトリパスのみを除外する
  4. リストでrmdirを1つずつ実行します
0
Ashish Ranjan