web-dev-qa-db-ja.com

ファイルが含まれていないフォルダー内のすべてのフォルダーとサブフォルダーを再帰的にクリーンアップします

フォルダ内のフォルダなどにたくさんのフォルダがあるフォルダがあります...フォルダの中にはファイルがあるものとないものがあります。ファイルのないディレクトリをすべて見つけて削除することで、メインフォルダーをクリーンアップしたいと思います。例の方が理にかなっているかもしれません:

だから私がこれから始めるなら:

  • mainFolder
    • folder1
      • folder1 (空の)
      • folder2
        • file.txt
      • folder3 (空の)
    • folder2
      • folder1 (空の)
      • folder2 (空の)
      • folder3
        • folder1
          • folder1 (空の)
    • folder3
      • folder1
        • file.txt

私はこれで終わるはずです:

  • mainFolder
    • folder1
      • folder2
        • file.txt
    • folder3
      • folder1
        • file.txt

そう:

  • /mainFolder/folder1/folder1はファイルがないため削除されました
  • /mainFolder/folder1/folder3ファイルがなかったため削除されました
  • /mainFolder/folder2ファイルがなく、すべてのサブフォルダーが空だったため、削除されました

これが理にかなっているといいのですが...

私が持っていた唯一のアイデアは、mainFolderから始めて、空のサブフォルダーを削除して各サブフォルダーを再帰的に移動することでした。

3
IMTheNachoMan

これがあなたが望むことをするかどうかを見てください:

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

空の深さ優先トラバーサルを使用してmainFolder内のディレクトリを検索し、それらのディレクトリを削除する必要があります。深さ優先トラバーサルを実行するため、サブディレクトリが削除されるため、親ディレクトリが空になると、findはそれを空として識別し、同様に削除します。

10
Andy Dalton

-delete-emptyの両方をサポートするfindの実装を使用する:

find mainFolder -type d -empty -delete

これにより、mainFolderをルートとするディレクトリ構造の深さ優先走査が実行され、そこにある空のディレクトリがすべて削除されます。

標準のfindを使用する:

find mainFolder -depth -type d -exec sh -c 'rmdir "$1" 2>/dev/null' sh {} ';'

これは、深さ優先の方法で構造をトラバースしながら、rmdirの下のeveryディレクトリでmainFolderを使用しようとします。 rmdirは空でないディレクトリを削除できないため、空のディレクトリのみが削除されます。 rmdirからのエラーは破棄されます。

rmdirを実行する前に各ディレクトリを明示的にテストするには:

find mainFolder -depth -type d -exec sh -c 'd="$1"; set -- "$d"/*; [ ! -e "$1" ] && rmdir "$d"' sh {} ';'

ただし、これはディレクトリに隠しファイルがないことを前提としています。

2
Kusalananda

解決

これを行うには、おそらくfindへのスイッチの組み合わせがいくつかありますが、Pythonアプローチの方が簡単だと思います(クロスプラットフォームであり、必要なわけではありません)。

import os

top = './mainFolder'
for root, dirs, files in os.walk(top, topdown=False):
    for name in dirs:
        dir_path = os.path.join(root, name)
        if not os.listdir(dir_path):  # An empty list is False
            os.rmdir(os.path.join(root, name))

セットアップとテスト

ファイルディレクトリを作成します

# https://stackoverflow.com/a/246128/295807
readonly script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

cd "$script_dir"

rm -rf mainFolder

mkdir -p mainFolder/{folder1/{folder1,folder2,folder3},folder2/{folder1,folder2,folder3/folder1/folder1},folder3/folder1}

touch mainFolder/folder1/folder2/file.txt
touch mainFolder/folder3/folder1/file.txt

テスト:

$ tree mainFolder/
mainFolder/
├── folder1
│   ├── folder1
│   ├── folder2
│   │   └── file.txt
│   └── folder3
├── folder2
│   ├── folder1
│   ├── folder2
│   └── folder3
│       └── folder1
│           └── folder1
└── folder3
    └── folder1
        └── file.txt

12 directories, 2 files

Pythonスクリプトを実行します:

python work.py

テスト:

$ tree mainFolder/
mainFolder/
├── folder1
│   └── folder2
│       └── file.txt
└── folder3
    └── folder1
        └── file.txt

4 directories, 2 files

注:Pythonの後でファイルがフォルダに追加されると、ファイルが空かどうかがチェックされますが、実際に消去される前に、Pythonは例外を発生させます!これらの2つのステップ間の時間はマイクロ秒で測定されるため、これは大した問題ではありませんが、注意する必要があります。

1
Ben