Elimina la directory principale (non vuota) se una directory secondaria specifica è vuota


11

Devo mantenere tutta la directory che contiene i file in una sottodirectory specifica, ma per eliminare tutte le directory in cui la sottodirectory è vuota.

Per essere più specifici ecco la struttura:

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

Le sottodirectory possono contenere o meno un file. Quindi ho bisogno di cancellare l'intera directory come '312311' e '566532' e solo '453453' dovrebbe essere lasciato con tutti i dati in esso perché ha un file nella cartella 'Registrazione' che è una directory specifica per me.

Ho visto molti post ma si collega a molti nomi di file specifici. Qualsiasi aiuto sarà molto apprezzato come devo fare molte volte in una settimana.


La registrazione è sempre al primo livello nella directory? Inoltre: tutte le cartelle al primo livello sono nella directory principale?
Jacob Vlijm,

A è la directory di livello superiore in cui contiene directory numerate. E nelle directory numerate contiene la cartella "Registrazione" e alcuni file "txt" come ad es. E in "Registrazione" può contenere o meno file ...
Derek James,

Rimuoverai l'immagine del tuo testo e inserirai il testo effettivo nella tua domanda. Le immagini del testo sono ingombranti da elaborare per noi. L'uso del testo reale è sostanzialmente più conveniente, tra le altre comodità intrinseche.
LD James

ho fatto lo stesso da te chiesto da James ..
Derek James,

Risposte:


12

Lo script seguente farà esattamente come lo descrivi, esso:

  1. elenca le cartelle all'interno di una directory
  2. Cerca all'interno di ciascuna delle cartelle una cartella denominata "Registrazione"

    • Se esiste ed è vuoto, elimina la sua cartella superiore
    • se non esiste, cancella anche la sua cartella superiore
    • i file al primo livello all'interno di A non verranno eliminati.

In un'immagine:

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

comporterà:

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

Il copione

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

Usare

  1. Copia lo script in un file vuoto, salvalo come delete_empty.py
  2. Eseguilo con la directory (full!) (Contieneinf i tuoi sottodir, A nel tuo esempio) come argomento dal comando:

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

Questo è tutto.

Spiegazione

Alimentando il contenuto della cartella "A" nello script,

os.listdir(dr)

elencherà le sue sottodirectory (e file). Poi:

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

proverà ad elencare il contenuto di ciascuna delle (sotto) cartelle, che genererà un errore se l'elemento è un file:

except NotADirectoryError
    pass

o se la cartella "Registrazione" non esiste affatto:

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

Se la cartella "Registrazione" esiste ed è vuota, la cartella superiore viene rimossa:

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

MODIFICARE

Inoltre, come richiesto nei commenti, una versione che controllerà più sottodirectory (nomi).

Nel caso in cui la directory contenga uno dei sottodirectory elencati (non vuoti), la directory viene mantenuta. Altrimenti verrà eliminato.

Usare

  1. Copia lo script in un file vuoto, salvalo come delete_empty.py
  2. Eseguilo con la directory (full!) (Contenente i tuoi sottodir, A nel tuo esempio) e i nomi dei sottodir come argomenti dal comando:

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

Questo è tutto.

Il copione

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

Nota

Per prima cosa, esegui una directory di prova per assicurarti che faccia esattamente quello che vuoi.


questo codice ha davvero aiutato e ha funzionato come detto. Grazie per il codice Davvero utile.
Derek James,

Supponiamo che se devo conservare e controllare due o più cartelle, come potrò fare questo codice? aggiungendo 'OR' o pipe '| 'da qualche parte .. suggerisci il sumthing!
Derek James,

Ciao @DerekJames che richiede solo una modifica minore, posterò questo pomeriggio.
Jacob Vlijm,

@Derek, aspetta, la cartella superiore dovrebbe essere rimossa se una delle cartelle è vuota o tutte? Potrebbero essercene più in una directory superiore?
Jacob Vlijm,

Supponiamo che @Jacob abbia due cartelle "Registrazione" e "Video". Dovrebbe controllare entrambi. Se una delle sottocartelle contiene il file, la cartella "635623" non deve essere eliminata. E anche la possibilità di aggiungere più cartelle per verificare se può essere fatto ..
Derek James

11

Utilizzando finde xargs:

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

(rimuovilo echoquando ti senti a tuo agio nell'identificare le directory corrette). La printf '%h\0parte stampa la directory principale (null terminated) - da 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
              ".".

Es .: dato

$ 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

poi

$ 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

trova un tipo-d nome-'registrazione' -empty -printf '% h \ 0' | xargs -0 echo rm -rf questo sta semplicemente stampando "rm -rf" E trova un tipo d -name 'Registrazione' -empty -printf '% h \ 0' | xargs -0 rm -rf non funziona ... Sto facendo qualcosa di sbagliato ..
Derek James,

@DerekJames è necessario sostituire A con la directory effettiva.
Jacob Vlijm,

Sarebbe ok inserire un'espressione regolare al posto del nome di registrazione poiché l'OP ha dato i nomi dei file con numeri, diciamo [\d]*?
George Udosen,

@JacobVlijm: ho sostituito con la directory attuale ma non si scrive ancora?
Derek James,

@DerekJames è strano! ha funzionato sul mio sistema, ma potresti aver dimenticato di inserire prima nella directory cd? Aspetta, non dovrebbe importare ...
Jacob Vlijm,

3

Ecco una soluzione bash più semplice:

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

Funziona perché rmdirfallirà se la directory non è vuota e &&impedirà l' rm -resecuzione se non ci rmdirriesce. Il glob */si assicura che stai lavorando solo sulle directory, quindi altri file non saranno interessati.


Pensiero intelligente! +1
Jacob Vlijm
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.