Trovare directory vuote UNIX


91

Devo trovare directory vuote per un determinato elenco di directory. Alcune directory contengono directory al loro interno.

Se anche le directory interne sono vuote posso dire che la directory principale è vuota altrimenti non è vuota.

Come posso testarlo?

Per esempio:

A>A1(file1),A2 this is not empty beacuse of file1
B>B1(no file) this is empty
C>C1,C2 this is empty

2
Penso che la risposta di Martin sia la più appropriata qui. La risposta attualmente accettata è solo uno pseudocodice incompleto.
Léo Léopold Hertz 준영

Risposte:


34

Controlla se find <dir> -type femette qualcosa. Ecco un esempio:

for dir in A B C; do
    [ -z "`find $dir -type f`" ] && echo "$dir is empty"
done

2
No, non produrrà sottodirectory. Ecco a cosa -type fserve.
Marcelo Cantos

Tuttavia, se ci sono file vuoti , la tua soluzione non produrrà il messaggio.
Yasir Arsanukaev

3
Yasir: Penso che una directory contenente un file vuoto ferito non sia essa stessa vuota. Non sarebbe il risultato corretto?
Ukko

2
@akostadinov: Se creo le directory ei file come indicato dall'OP - mkdir A B C A/A1 A/A2 B/B1 C/C1 C/C2; touch A/A1/file1- ed eseguo il codice nella mia risposta, segnala che B e C sono vuoti, come richiesto dall'OP. Quindi dovrai essere un po 'più specifico di "non funzionerà".
Marcelo Cantos

1
Se sei un noob di Bash come me, controlla cosa significa -z qui .
OmarOthman

257

Dipende un po 'da cosa vuoi fare con le directory vuote. Uso il comando seguente quando desidero eliminare tutte le directory vuote all'interno di un albero, ad esempio testdirectory.

find test -depth -empty -delete

Una cosa da notare sul comando sopra è che rimuoverà anche i file vuoti , quindi usa l' opzione -type d per evitarlo.

find test -depth -type d -empty -delete

Rilascia -deleteper vedere i file e le directory corrispondenti.

Se la tua definizione di un albero di directory vuoto è che non contiene file, puoi unire qualcosa in base al fatto che find test -type frestituisca qualcosa.

find è una grande utility e RTFM presto e spesso per capire davvero quanto può fare :-)


8
-delete implica -depth (almeno per GNU findutils 4.4.2)
Dr. Person Person II

4
non sapevo -empty, così conveniente!
Raffi

2
Tuttavia su macchine che non sono l'ultima e la migliore Linux. (EG Solaris), quindi non hai funzionalità di ricerca fantasiose come -empty o -delete.
anthony

3
Su MacOS-X, per directory quasi vuote, esegui find test -name ".DS_Store" -deleteprima, poi il -empty deletecomando. Nota anche, mi piace alla pushddirectory principale, in modo che find testdiventi find ., ma il resto dei comandi è lo stesso.
Olie

1
@Martin Puoi per favore aggiungere la definizione di -depthqui, ad esempio, perché find esegua un attraversamento in profondità, cioè le directory vengono visitate in post-ordine e tutte le voci in una directory agiranno prima della directory stessa. Penso che sia rilevante qui.
Léo Léopold Hertz 준영

49

Puoi usare il seguente comando:

find . -type d -empty

1
-empty funziona solo se la directory corrente è completamente vuota, non se la sottostruttura non contiene file.
Marcelo Cantos

@soField Tested find. -type d -empty con FreeBSD e CentOS. Funziona bene. Qual è il tuo sistema operativo?
mosg

1
hp-ux quindi non ci sono parametri vuoti
soField

@soField Quindi, vedi, che è meglio (per tutti noi) pubblicare questi dati all'inizio della tua domanda ...
mosg

2
find non ha nemmeno -empty su solaris, ma ha -depth per applicare l'attraversamento in profondità in modo che le sottodirectory vuote possano essere eliminate prima che la directory genitore sia controllata per il vuoto.
eirikma

26
find directory -mindepth 1 -type d -empty -delete

Questa è la versione che ho trovato più interessante. Se eseguito dall'interno della directory , eliminerà tutte le directory vuote sottostanti (una directory è considerata vuota se contiene solo directory vuote).

L'opzione mindepth impedisce che la directory stessa venga eliminata se risulta essere vuota.


2
Puoi seguirlo rmdir --ignore-fail-on-non-empty -p directoryper sbarazzarti anche dei genitori.
Pete Peterson

@Pete Peterson Il mio comando sembra rimuovere le directory che contengono solo altre directory vuote (che è ciò che anche OP sembra volere). Noto che il tuo comando di solito lascia l'utente in una directory con un i-node mancante anche se esegue ciò che desidera, il che potrebbe creare confusione. Forse sto perdendo il punto.
Dr. Person Person II

23

find . -type d -empty

trova ed elenca le directory e le sottodirectory vuote nell'albero corrente. Ad esempio, elenco risultante di directory e sottodirectory vuote:

./2047
./2032
./2049
./2063
./NRCP26LUCcct1/2039
./NRCP26LUCcct1/2054
./NRCP26LUCcct1/2075
./NRCP26LUCcct1/2070

Nessuna operazione viene eseguita sulle directory. Sono semplicemente elencati. Questo funziona per me.


16

Trova le directory vuote

Per trovare solo directory vuote (come specificato nel titolo della domanda), la risposta del mosg è corretta:

find -type d -empty

Ma -emptypotrebbe non essere disponibile su findversioni molto vecchie (questo è il caso di HP-UX, ad esempio). Se questo è il tuo caso, consulta le tecniche descritte nella sezione seguente. Una directory è vuota? .

Elimina directory vuote

Questo è un po 'complicato: supponiamo che una directory MyDircontenga directory vuote. Dopo aver rimosso queste directory vuote, MyDirdiventerà una directory vuota e dovrebbe essere rimossa. Pertanto utilizzo il comando rmdircon l'opzione --parents(o -p) che rimuove anche le directory padre quando possibile:

find -type d -empty -exec rmdir -vp --ignore-fail-on-non-empty {} +

Nella findversione precedente l'istruzione +non è ancora supportata, quindi è possibile utilizzare ;invece:

find -type d -empty -exec rmdir -vp --ignore-fail-on-non-empty {} `;`

Una directory è vuota?

La maggior parte di queste risposte spiega come verificare se una directory è vuota. Pertanto fornisco qui le tre diverse tecniche che conosco:

  1. [ $(find your/dir -prune -empty) = your/dir ]

    d=your/dir
    if [ x$(find "$d" -prune -empty) = x"$d" ]
    then
      echo "empty (directory or file)"
    else
      echo "contains files (or does not exist)"
    fi

    una variazione:

    d=your/dir
    if [ x$(find "$d" -prune -empty -type d) = x"$d" ]
    then
      echo "empty directory"
    else
      echo "contains files (or does not exist or is not a directory)"
    fi

    Spiegazione:

    • find -pruneè simile find -maxdepth 0all'utilizzo di meno caratteri
    • find -type d stampa solo le directory
    • find -empty stampa le directory e i file vuoti

      > mkdir -v empty1 empty2 not_empty
      mkdir: created directory 'empty1'
      mkdir: created directory 'empty2'
      mkdir: created directory 'not_empty'
      > touch not_empty/file
      > find empty1 empty2 not_empty -prune -empty
      empty1
      empty2
  2. (( ${#files} ))

    Questo trucco è al 100% bashma invoca (genera) un sub-shell. L'idea è di Bruno De Fraine e migliorata dal commento di teambob . Consiglio questo se usi e se il tuo script non deve essere portabile.

    files=$(shopt -s nullglob dotglob; echo your/dir/*)
    if (( ${#files} ))
    then 
      echo "contains files"
    else 
      echo "empty (or does not exist or is a file)"
    fi

    Nota: nessuna differenza tra una directory vuota e una inesistente (e anche quando il percorso fornito è un file).

  3. [ $(ls -A your/dir) ]

    Questo trucco è ispirato dall'articolo di nixCraft pubblicato nel 2007. Andrew Taylor ha risposto nel 2008 e gr8can8dian nel 2011.

    if [ "$(ls -A your/dir)" ]
    then
      echo "contains files"
    else
      echo "empty (or does not exist or is a file)"
    fi

    o la versione bashism di una riga:

    [[ "$(ls -A your/dir)" ]] && echo "contains files" || echo "empty or ..."

    Nota: ls ritorna $?=2quando la directory non esiste. Ma nessuna differenza tra un file e una directory vuota.


rmdir -vpmi ha aiutato immensamente poiché avevo bisogno non solo di eliminare tutte le directory vuote sotto una radice, ma controllare le directory vuote e le directory padre dopo aver eliminato un file. Nella mia situazione le directory vuote vanno bene fintanto che non sono nell'albero da cui sto attualmente rimuovendo un file. Grazie!
Ethan Hohensee

2

Questa funzione ricorsiva sembrerebbe fare il trucco:

# Bash
findempty() {
    find ${1:-.} -mindepth 1 -maxdepth 1 -type d | while read -r dir
    do
        if [[ -z "$(find "$dir" -mindepth 1 -type f)" ]] >/dev/null
        then
            findempty "$dir"
            echo "$dir"
        fi
    done
}

Data questa struttura di directory di esempio:

    .
    | - dir1 /
    | - dir2 /
    | `- dirB /
    | - dir3 /
    | `- dirC /
    | `- file5
    | - dir4 /
    | | - dirD /
    | `- file4
    `- dir5 /
        `- dirE /
            `- dir_V /

Il risultato dell'esecuzione di quella funzione sarebbe:

    ./dir1
    ./dir5/dirE/dir_V
    ./dir5/dirE
    ./dir5
    ./dir2/dirB
    ./dir2

che manca /dir4/dirD. Se sposti la chiamata ricorsiva findempty "$dir"dopo fi, la funzione includerà quella directory nei suoi risultati.


2

Che ne dici rmdir *? Quel comando fallirà su directory non vuote.


Qualcosa che ho fatto a volte, per la pulizia generale. Anche fatto cose come rmdir */*/* */* * Sebbene non gestisca i "file punto" ma in situazioni manuali (pulizia dei file di dati) generalmente non ti aspetti "file punto". I metodi ricorsivi, tuttavia, sono per una pulizia generale più automatizzata, specialmente in strutture di directory molto grandi.
Anthony il

In un caso era più complicato in quanto avevo bisogno di rimuovere directory vuote in cui "vuote" includeva directory che potevano contenere un singolo file "readme". Qualsiasi altra cosa nella directory e non era "vuota". In quell'esempio la struttura delle directory comprendeva decine di migliaia di sottodirectory.
anthony

1

Il comando seguente restituisce 1 se una directory è vuota (o non esiste) e 0 altrimenti (quindi è possibile invertire il codice di ritorno con !in uno script di shell):

find $dir -type d -prune -empty -exec false {} +

0

Ho creato una struttura semplice come segue:

test/
test/test2/
test/test2/test2.2/
test/test3/
test/test3/file

Il test/test3/filecontiene del testo spazzatura.

L'emissione find test -emptyrestituisce " test/test2/test2.2" come l'unica directory vuota.


l'operazione richiede la restituzione anche di test / test2

Infatti. Ma ho pensato che potesse leggere la pagina man di trova per andare oltre. Uno script che regola la profondità in base ai risultati funzionerebbe perfettamente.
James Sumners,

Questa è stata la versione più utile per me, grazie
Andreas

0

un approccio semplice sarebbe,

$ [ "$(ls -A /path/to/direcory)" ] && echo "not empty" || echo "its empty"

anche,

if [ "$(ls -A /path/to/direcory)" ]; then
   echo "its not empty"
else 
   echo "empty directory"

0
find . -name -type d -ls |awk '($2==0){print $11}'
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.