特定の子ディレクトリが空の場合、親ディレクトリを削除します(空ではない)


11

特定のサブディレクトリにファイルを含むすべてのディレクトリを保持する必要がありますが、サブディレクトリが空のすべてのディレクトリを削除する必要があります。

より具体的には、構造です。

A
|
|--------312311
|       |
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|
|--------453453
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------566532
|       |----Recording
|       |----a.txt
|       |----b.txt

サブディレクトリにはファイルが含まれている場合と含まれていない場合があります。そのため、「312311」や「566532」などのディレクトリ全体を削除する必要があり、「453453」のみにすべてのデータを残しておく必要があります。

多くの投稿を見ましたが、多くの特定のファイル名にリンクしています。週に何度もやらなければならないので、どんな助けも大歓迎です。


録音は常にディレクトリの最初のレベルにありますか?また、すべてのフォルダーはメインディレクトリ内の最初のレベルにありますか?
ジェイコブVlijm

Aは、番号付きディレクトリが含まれる最上位ディレクトリです。そして、番号の付いたディレクトリには、「Recording」フォルダと「txt」ファイルなどが含まれています。また、「録音」では、ファイルが含まれている場合と含まれていない場合があります。
Derek James

テキストの写真を削除して、実際のテキストを質問に入れてください。テキストの写真は処理が面倒です。他の固有の便利さの中でも、実際のテキストを使用する方がはるかに便利です。
LDジェームズ

私はあなたに頼ま同じでしたジェームズ...
デレク・ジェームズ

回答:


12

以下のスクリプトは、説明したとおりに実行します。

  1. ディレクトリ内のフォルダをリストします
  2. 「Recording」という名前のフォルダーを各フォルダー内で探します

    • 存在し空の場合、その上位フォルダーを削除します
    • 存在しない場合は、上位フォルダーも削除します
    • A内の最初のレベルのファイルは削除されません。

画像内:

A
|
|--------123456
|       |
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|
|--------635623
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------123456
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|--------Monkey.txt

結果として:

A
|
|
|--------635623
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------Monkey.txt

スクリプト

#!/usr/bin/env python3
import os
import sys
import shutil

dr = sys.argv[1]

def path(*args):
    return os.path.join(*args)

for d in os.listdir(dr):
    try:
        if not os.listdir(path(dr, d, "Recording")):
            shutil.rmtree(path(dr,d))
    except FileNotFoundError:
        shutil.rmtree(path(dr,d))
    except NotADirectoryError:
        pass

使用するには

  1. スクリプトを空のファイルにコピーして、名前を付けて保存します delete_empty.py
  2. (full!)ディレクトリ(サブディレクトリを含む、例ではA)をコマンドの引数として実行します。

    python3 /path/to/delete_empty.py /path/to/directory
    

それでおしまい。

説明

フォルダ「A」のコンテンツをスクリプトにフィードし、

os.listdir(dr)

そのサブディレクトリ(およびファイル)をリストします。次に:

if not os.listdir(path(dr, d, "Recording"))

各(サブ)フォルダーのコンテンツをリストしようとしますが、アイテムがファイルの場合はエラーが発生します。

except NotADirectoryError
    pass

または、フォルダ「Recording」がまったく存在しない場合:

FileNotFoundError
    shutil.rmtree(path(dr,d))

フォルダ「Recording」が存在し空の場合、上位のフォルダは削除されます:

if not os.listdir(path(dr, d, "Recording")):
    shutil.rmtree(path(dr,d))

編集

さらに、コメントで要求されているように、複数のサブディレクトリ(名前)をチェックするバージョン。

場合にディレクトリが含まれて任意の列挙された(未空の)サブディレクトリのディレクトリが保持されています。それ以外の場合は削除されます。

使用するには

  1. スクリプトを空のファイルにコピーして、名前を付けて保存します delete_empty.py
  2. (full!)ディレクトリ(サブディレクトリ、例ではAを含む)と、コマンドによる引数としてサブディレクトリの名前を指定して実行します。

    python3 /path/to/delete_empty.py /path/to/directory <subdir1> <subdir2> <subdir3>
    

それでおしまい。

スクリプト

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]; matches = sys.argv[2:]

def path(*args):
    return os.path.join(*args)

for d in os.listdir(dr):
    # delete directory *unless* either one of the listed subdirs has files
    keep = False
    # check for each of the listed subdirs(names)
    for name in matches:
        try:
            if os.listdir(path(dr, d, name)):
                keep = True
                break
        except NotADirectoryError:
            # if the item is not a dir, no use for other names to check
            keep = True
            break
        except FileNotFoundError:
            # if the name (subdir) does not exist, check for the next
            pass
    if not keep:
        # if there is no reason to keep --> delete
        shutil.rmtree(path(dr,d))

注意

最初にテストディレクトリで実行して、希望どおりに動作することを確認してください。


このコードは本当に役に立ち、述べたように機能しました。コードをありがとう。本当に助かりました。
デレクジェームズ

2つ以上のフォルダーを保持してチェックする必要がある場合、このコードでどのようにできるのでしょうか?「OR」またはパイプを追加する| 'どこか..サミングを提案!
デレクジェームズ

こんにちは@DerekJames、ちょっとした編集だけが必要です。今日の午後に投稿します。
ジェイコブVlijm

@Derek、待ってください。いずれかのフォルダーが空の場合、またはすべての場合、上位フォルダーを削除する必要がありますか?1つの上位ディレクトリにそれらが複数存在する可能性はありますか?
ジェイコブVlijm

@Jacobに、「Recording」と「Video」という2つのフォルダーがあるとします。両方をチェックする必要があります。サブフォルダーのいずれかにファイルが含まれている場合、フォルダー「635623」は削除されません。そしてまた、それを行うことができるかどうかをチェックするために複数のフォルダを追加する機能。..
デレク・ジェームズ

11

findand を使用xargs

find A -type d -name 'Recording' -empty -printf '%h\0' | xargs -0 echo rm -rf

echo正しいディレクトリを識別していることに満足したら削除してください)。printf '%h\0から-一部は(NULLで終了)親ディレクトリを表示しますman find

       %h     Leading directories of file's name (all but the last ele‐
              ment).  If the file name contains no slashes (since it is
              in  the  current  directory)  the %h specifier expands to
              ".".

例:与えられた

$ tree A
A
├── 312311
│   ├── a.txt
│   ├── b.txt
│   └── Recording
├── 453453
│   ├── a.txt
│   ├── b.txt
│   └── Recording
│       └── a.mp3
└── 566532
    ├── a.txt
    ├── b.txt
    └── Recording

6 directories, 7 files

それから

$ find A -type d -name 'Recording' -empty -printf '%h\0' | xargs -0 rm -rf
$ 
$ tree A
A
└── 453453
    ├── a.txt
    ├── b.txt
    └── Recording
        └── a.mp3

2 directories, 3 files

-type d -name 'Recording'を検索-empty -printf '%h \ 0' | xargs -0 echo rm -rfこれは、単に「rm -rf」と出力し、A -type d -name 'Recording' -empty -printf '%h \ 0'を見つけます。xargsの-0 RM -rfが動作していない...アム私は何か間違っている...
デレク・ジェームズ

@DerekJamesは、Aを実際のディレクトリに置き換える必要があります。
ジェイコブVlijm

OPがファイル名に数字を付けたので、録音名の代わりに正規表現を入れても大丈夫でしょう[\d]*か?
ジョージウドセン

@JacobVlijm:実際のディレクトリに置き換えましたが、まだ壊れていませんか?
デレクジェームズ

@DerekJamesそれは奇妙です!それは私のシステムで動作しましたが、最初にディレクトリにcdするのを忘れていたかもしれませんか?Waitwait、その...問題ではないはず
ジェイコブVlijm

3

よりシンプルなbashソリューションを次に示します。

for d in */; do rmdir "$d/Recording" && rm -r "$d"; done

ので、それは働くrmdirディレクトリが空でない場合は失敗し、&&防ぐことができますrm -rしない限り、実行されてからrmdir成功しました。glob */は、ディレクトリでのみ作業していることを確認するため、他のファイルは影響を受けません。


スマート思考!+1
ジェイコブヴリム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.