空フォルダ・ディレクトリを削除する

ORESAMA / 流星ダンスフロア -MUSIC VIDEO- (TVアニメ『魔法陣グルグル』2クール目OP主題歌)

(ORESAMA / 流星ダンスフロア)

アニメ『魔法陣グルグル』(2017)の主題歌です。
ORESAMAの歌から入って、アニメを見たのですが、すっごい面白いですこのアニメ。めんどくさいことは全てすっ飛ばし。なんならみるのがめんどくさいなら試聴を途中でやめられるし、ストーリーを忘れた後で試聴を再開しても普通に楽しめるアニメです。

今回は、めんどくさい空フォルダ・ディレクトリの削除です。
空フォルダ、空ディレクトリの削除はrmdirを使えば簡単なんですが、空であることが前提なので、中にファイルが存在していたら使えないんです。
いやいや-pオプションがあるでしょ。いえ、それもだめです。-pオプションは、最下層のディレクトリまでを指定しないとディレクトリが消せないんです。

結局フォルダ・ディレクトリが空かどうか知るには、ディレクトリをぐるぐる巡回しないといけないわけですが、Linux(Unix)では面倒なことはすべてfindコマンドがやってくれます。

まずは実験用ディレクトリを作っておきましょう。適当に数階層のディレクトリ、各階にファイルを生成。

takk@deb9:~/tmp$ mkdir -p dir1/111/222/333/444
takk@deb9:~/tmp$ mkdir -p dir1/aaa/bbb/ccc/ddd
takk@deb9:~/tmp$ for i in `find`;do touch $i/file.txt;done
takk@deb9:~/tmp$ find
.
./dir1
./dir1/file.txt
./dir1/aaa
./dir1/aaa/bbb
./dir1/aaa/bbb/ccc
./dir1/aaa/bbb/ccc/file.txt
./dir1/aaa/bbb/ccc/ddd
./dir1/aaa/bbb/ccc/ddd/file.txt
./dir1/aaa/bbb/file.txt
./dir1/aaa/file.txt
./dir1/111
./dir1/111/file.txt
./dir1/111/222
./dir1/111/222/333
./dir1/111/222/333/file.txt
./dir1/111/222/333/444
./dir1/111/222/333/444/file.txt
./dir1/111/222/file.txt
./file.txt
takk@deb9:~/tmp$

さらにディレクトリを増やして、一部ファイルを削除して、空ディレクトリを作っておきます。

takk@deb9:~/tmp$ cp -r dir1 dir2
takk@deb9:~/tmp$ find dir2/aaa -type f | xargs rm
takk@deb9:~/tmp$ 

後で比較するため、この状態のディレクトリの一覧を保存しておきます。

takk@deb9:~/tmp$ find -type d > origin
takk@deb9:~/tmp$

では、空ディレクトリを抽出しましょう。-emptyオプションで抽出できます。

takk@deb9:~/tmp$ find -type d -empty
./dir2/aaa/bbb/ccc/ddd
takk@deb9:~/tmp$

削除するには、-deleteオプションも併用します。
すべての空ディレクトリが削除されます。

takk@deb9:~$ find . -type d -empty -delete

元のディレクトリ一覧と比較してみます。

takk@deb9:~/tmp$ find -type d | diff origin -
12,15d11
< ./dir2/aaa
< ./dir2/aaa/bbb
< ./dir2/aaa/bbb/ccc
< ./dir2/aaa/bbb/ccc/ddd
takk@deb9:~/tmp$

空ディレクトリのみ消えてますね。

では、Windowsです。
Linuxと同じように、実験用フォルダ作ります。

C:\Users\takk\tmp>mkdir dir1\111\222\333\444
C:\Users\takk\tmp>mkdir dir1\aaa\bbb\ccc\ddd
C:\Users\takk\tmp>powershell "gci -r -n -ad | % {ni -itemtype file $_/file.txt}"
C:\Users\takk\tmp>powershell "cp -r dir1 dir2"
C:\Users\takk\tmp>powershell "cd dir2/aaa;gci -r -n -af | % {rm $_}"
C:\Users\takk\tmp>

削除前フォルダ一覧として保存しておきます。

C:\Users\takk\tmp>powershell "gci -r -n -ad > origin"

ファイルが存在するかどうかは、ファイルを抽出した時のオブジェクト数が0かどうかで判断すればよいです。各フォルダに含まれるファイル数を一覧表示してみます。

C:\Users\takk\tmp>powershell "cd dir2;gci -r -n -ad | %{Write-Host $_ (gci -r -n
 -af $_).count}"
111 4
aaa 0
111\222 3
111\222\333 2
111\222\333\444 1
aaa\bbb 0
aaa\bbb\ccc 0
aaa\bbb\ccc\ddd 0

C:\Users\takk\tmp>

次は、カウントが0かどうかの真偽一覧。

C:\Users\takk\tmp>powershell "cd dir2;gci -r -n -ad | %{ Write-Host ( (gci -r -n
 -af $_).count -eq 0 ) $_}"
False 111
True aaa
False 111\222
False 111\222\333
False 111\222\333\444
True aaa\bbb
True aaa\bbb\ccc
True aaa\bbb\ccc\ddd

C:\Users\takk\tmp>

真偽分かれば、ファイルが存在しないフォルダが分かるので、削除するだけです。

C:\Users\takk\tmp>powershell "cd dir2/aaa;gci -r -n -ad | %{ if( (gci -r -n -af $_).
count -eq 0 ){rm -r $_}}"

C:\Users\takk\tmp>

元フォルダの一覧と比較してみます。

C:\Users\takk\tmp>powershell "$a=cat origin;$b=(gci -r -n -ad);diff $a $b"

InputObject                             SideIndicator
-----------                             -------------
dir2\aaa\bbb                            <=
dir2\aaa\bbb\ccc                        <=
dir2\aaa\bbb\ccc\ddd                    <=



C:\Users\takk\tmp>

この通り、空フォルダがきれいに消えました。

コメント

タイトルとURLをコピーしました