it-swarm.com.de

Löschen Sie das übergeordnete Verzeichnis (nicht leer), wenn ein bestimmtes untergeordnetes Verzeichnis leer ist

Ich muss das ganze Verzeichnis behalten, das Akten in einem spezifischen Unterverzeichnis enthält, aber alle Verzeichnisse stillstehen löschen, in denen Unterverzeichnis leer ist.

Genauer ist hier das Bild:

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

Die Unterverzeichnisse können eine Datei enthalten oder nicht. Ich muss also das gesamte Verzeichnis wie '312311' und '566532' löschen und nur '453453' sollte mit allen Daten darin belassen werden, da es eine Datei im 'Aufnahme'-Ordner gibt, die ein spezielles Verzeichnis für mich ist.

Ich habe viele Posts gesehen, aber es gibt Links zu vielen bestimmten Dateinamen. Jede Hilfe wird sehr geschätzt, da ich in einer Woche viele Male tun muss.

11
Derek James

Das folgende Skript funktioniert genau so, wie Sie es beschreiben:

  1. listet die Ordner in einem Verzeichnis auf
  2. Sucht in jedem Ordner nach einem Ordner mit dem Namen "Aufnahme"

    • Wenn es existiert und leer ist, wird der übergeordnete Ordner gelöscht
    • wenn es nicht gibt , wird auch der übergeordnete Ordner gelöscht
    • Dateien auf der ersten Ebene in A werden nicht gelöscht.

In einem Bild:

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

wird darin enden, dass:

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

Das Drehbuch

#!/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

Benutzen

  1. Kopieren Sie das Skript in eine leere Datei und speichern Sie es als delete_empty.py
  2. Führen Sie es mit dem (vollständigen!) Verzeichnis (enthält Ihre Unterverzeichnisse, A in Ihrem Beispiel) als Argument durch den Befehl aus:

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

Das ist es.

Erläuterung

Feeding den Inhalt Ihres Ordners "A" an das Skript,

os.listdir(dr)

listet seine Unterverzeichnisse (und Dateien) auf. Dann:

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

versucht, den Inhalt jedes (Unter-) Ordners aufzulisten, was einen Fehler auslöst, wenn es sich bei dem Element um eine Datei handelt:

except NotADirectoryError
    pass

oder falls der Ordner "Aufnahme" gar nicht existiert:

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

Wenn der Ordner "Aufnahme" existiert und leer ist, wird der übergeordnete Ordner entfernt:

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

BEARBEITEN

Zusätzlich, wie in den Kommentaren angefordert, eine Version, die nach mehreren Unterverzeichnissen (Namen) sucht.

Falls das Verzeichnis beliebige der aufgelisteten (nicht leeren) Unterverzeichnisse enthält, wird das Verzeichnis beibehalten. Sonst wird es gelöscht.

Benutzen

  1. Kopieren Sie das Skript in eine leere Datei und speichern Sie es als delete_empty.py
  2. Führen Sie es mit dem (vollständigen!) Verzeichnis (das Ihre Unterverzeichnisse enthält, A in Ihrem Beispiel) und den Namen der Unterverzeichnisse als Argumente durch den Befehl aus:

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

Das ist es.

Das Drehbuch

#!/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))

Hinweis

Bitte führen Sie zuerst ein Testverzeichnis aus, um sicherzustellen, dass es genau das tut, was Sie wollen.

12
Jacob Vlijm

Mit find und xargs:

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

(Entfernen Sie das echo, sobald Sie sicher sind, dass es die richtigen Verzeichnisse identifiziert). Der Teil printf '%h\0 druckt das (nullterminierte) übergeordnete Verzeichnis aus 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
              ".".

Bsp .: gegeben

$ 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

dann

$ 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
11
steeldriver

Hier ist eine einfachere Bash-Lösung:

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

Es funktioniert, weil rmdir fehlschlägt, wenn das Verzeichnis nicht leer ist, und && verhindert, dass rm -r ausgeführt wird, es sei denn, rmdir ist erfolgreich. Der Globus */ stellt sicher, dass Sie nur an den Verzeichnissen arbeiten, damit andere Dateien nicht betroffen sind.

3
JoL