Elimina le sottocartelle vuote, mantieni la cartella principale


15

Quando uso

find /home/user/parentdir -type d -empty -delete

cerca ricorsivamente all'interno delle sottocartelle vuote /home/user/parentdire le elimina. Ma se /home/user/parentdirè anche vuoto, cancella anche la parentdircartella, il che è indesiderabile per me.

Voglio mantenerlo parentdirsu rsyncalcuni file per il backup o il cloud. Dopo l'elaborazione, devo eliminare le cartelle vuote, ma sembra poco produttivo ricrearle parentdirogni volta.

Qualche suggerimento da tenere parentdir? Ho pensato di creare un .nocopyfile al suo interno ed escluderlo rsync, ma sembra eccessivo. C'è un modo più elegante?


se aggiungi una barra / alla fine di / parentdir (cioè / parentdir /) questo fa la differenza?
Graham,

6
-mindepth 1?
Steeldriver,

@Graham / parentdir / elimina anche parentdir, quindi non fa differenza.
TNT,

ah, vedo che alla fine ho perso il * che @Amourk menziona nella sua risposta.
Graham,

Risposte:


25

Semplicemente find /home/user/parentdir -mindepth 1 -type d -empty -delete.

Guarda:

$ mkdir -p test1/test2
$ find test1 -type d
test1
test1/test2
$ find test1 -mindepth 1  -type d
test1/test2

La find /home/user/parentdir/* risposta di AmourK è indesiderabile quando ci sono molti file ed è complicata.


15

Aggiungendo /*alla fine di parentdir, si sta eseguendo l'azione su tutti i sottodirectory di parentdir anziché su parentdirse stessa. E così allo stesso modo /home/user/non viene eliminato nel vecchio comando, parentdirnon verrà eliminato nel comando seguente. *viene chiamato operatore glob e corrisponde a qualsiasi stringa di caratteri.

find /home/user/parentdir/* -type d -empty -delete


7
Una cosa da tenere presente con questo approccio è che se c'è un gran numero di file /home/user/parentdir/, il glob espanso potrebbe superare ARG_MAX, causando un errore troppo lungo nella lista degli argomenti . È possibile ridurre la possibilità che ciò accada modificando il glob in */modo che corrisponda solo alle directory.
Steeldriver,

12
Attenzione anche che questo non troverà alcun bambino che inizia con un punto. E un giorno te ne renderai conto, e se fai anche una ricerca per ". *" Ti troverai in un mondo enorme di dolore (perché ". *" Corrisponde a ".."). Chiedimi come lo so.
Glenn Willen,

1
@GlennWillen perché penso che dovremmo essere seduti in un bar con bevande davanti a noi prima di chiederti di raccontare questa storia?
Monty Harder,

@MontyHarder Per fortuna non è stato così male come avrebbe potuto essere. Era sul mio primo sistema Unix, che era una macchina Solaris di proprietà del mio liceo. Grazie a Dio non stavo correndo "rm", ma piuttosto "chown". Stavo usando root per provare a riparare la proprietà di tutto nella mia home directory. Invece mi sono dato la proprietà di OGNI home directory (e tutti i loro contenuti) e poi ho dovuto rimetterli tutti.
Glenn Willen,

Ho avuto un collega che ha formato un nuovo dipendente su come installare un software. Si trattava di andare /tmp, creare una sottodirectory, decomprimere un tarball compresso lì, eseguire il programma di installazione e ripulire. Il neofita pensava che rm -rf /tmp/foo-installfosse il modo giusto per farlo, e mentre la mano esperta diceva "Noooooo" nella sua migliore impressione di Darth-Vader-at-the-end-of-Episode-III, il newb scoprì nel modo più duro quanto vicino I tasti / e Invio erano tra loro. Abbiamo dovuto eseguire l'avvio dal disco di ripristino del software di backup e ricaricare l'intero server dal nastro.
Monty Harder,

0

se hai installato php-cli,

printf %s $(pwd) | php -r 'function f(string $dir){var_dump($dir);$dir.=DIRECTORY_SEPARATOR;foreach(glob("$dir*",GLOB_ONLYDIR) as $d){f($d);}global $original;if(substr($dir,0,-strlen(DIRECTORY_SEPARATOR))!==$original && empty(glob("$dir*"))){rmdir($dir);}}f(($original=stream_get_contents(STDIN)));'

volevi foreach (RecursiveIteratorIterator(RecursiveDirectoryIterator($dir)) as $p) if (empty($skipped)) $skipped = TRUE; elseif ($p->isDir()) @rmdir($p->getPathname());o qualcosa di simile a quello. $skippedsi occupa di saltare il primo, @rmdirtenta di rimuovere una directory e silenziosamente (che è la @) non riesce se non vuoto.
chx,

0

Quando hai solo bisogno di un livello (lasciare una cartella principale, ma eliminare le cartelle secondarie vuote), un trucco semplice è usare rmdir.

rmdir parent/*

Elimina tutte le sottocartelle vuote, ma stampa solo un errore per file e cartelle non vuote.

Questo non funziona in modo ricorsivo, ma quando si conosce la struttura delle cartelle potrebbe essere il modo più veloce per fare qualcosa del genere

rmdir parent/*/*/* # deletes parent/a/b/c when empty
rmdir parent/*/* # deletes parent/a/b when it is now empty
rmdir parent/* # deletes parent/a when it is now empty

Vantaggio: facile da ricordare, veloce da digitare, scarso potenziale per la scelta di un parametro errato.
Svantaggio: meno flessibile, probabilmente molti messaggi di errore nel tuo terminale.

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.