web-dev-qa-db-ja.com

再帰的なrmdirの効果を実現する

私が見る限り、rmdirにはオプション-rがあり、ディレクトリのみが含まれ、ツリーのどこにもファイルが含まれていない場合にのみ、引数の参照を削除できた可能性があります。それを行う最も簡単な方法は何ですか?

1
Toothrot

GNU find、および現在のBSDのfind(macOSを含む)には-deleteこれに使用できるアクション:

find . -type d -empty -delete

空のディレクトリを見つけて削除します。 -deleteアクションは深さ優先処理をアクティブにし、他のディレクトリのみを含み、サブディレクトリにファイルを含まないディレクトリが削除されるようにします。

4
Stephen Kitt

Zshシェルを使用して、引数を(サブ)ディレクトリのリストに再帰的に展開し、深さで逆ソートすることができます。次に、rmdirはリストを順番に処理できます。各ディレクトリが空の場合にのみ成功し、空でない場合は警告を表示します(そしてnotディレクトリを削除します)。これにより、空のディレクトリツリーが削除され、ディレクトリが空でない場合に警告が表示されます。

bydepth関数を ステファンの答えはこちら から借りました。

bydepth() REPLY=${REPLY//[^\/]}
rmdir **/(/O+bydepth)

bydepth関数は、スラッシュ以外の文字をすべて削除することにより、REPLY変数を(再)設定します。次に、そのREPLY文字列は、glob修飾子O+の並べ替え関数によって使用され、最も長いものから順に並べられます。他のglob修飾子は/で、ディレクトリのみを選択します。最初の**/ワイルドカードは、現在のディレクトリから再帰的に展開するようにzshに指示します。

サンプル実行:

$ : no files exist
$ mkdir -p a/b/c/d
$ find .
.
./a
./a/b
./a/b/c
./a/b/c/d
$ rmdir **/(/O+bydepth)
$ find .
.
$ 
$ : a file exists
$ mkdir -p a/b/c/d
$ touch a/b/c/somefile
$ find .
.
./a
./a/b
./a/b/c
./a/b/c/d
./a/b/c/somefile
$ rmdir **/(/O+bydepth)
rmdir: failed to remove ‘a/b/c/’: Directory not empty
rmdir: failed to remove ‘a/b/’: Directory not empty
rmdir: failed to remove ‘a/’: Directory not empty
$ find .
.
./a
./a/b
./a/b/c
./a/b/c/somefile
0
Jeff Schaller