Voglio eliminare ricorsivamente tutti i file a cui non si accede da un po' di tempo nella cartella a , ad eccezione di tutti i file nella sottocartella b .
find a ( -name b -prune ) -o -type f -delete
Tuttavia, ricevo un messaggio di errore:
trova:l'azione -delete attiva automaticamente -depth, ma -prune non esegue
nulla quando -depth è attivo. Se vuoi continuare comunque,
usa esplicitamente l'opzione -depth.
Aggiunta di -depth causa tutti i file in b da includere, che deve non succedere.
Qualcuno conosce un modo sicuro per farlo funzionare?
Risposta accettata:
un modo è usare -exec rm invece di -delete .
find a ( -name b -prune ) -o -type f -exec rm {} +
in alternativa usa -not -path invece di -prune :
find a -not -path "*/b*" -type f -delete
Spiegazione del perché -prune collide con -delete :
trova lamentele quando provi a usare -delete con -prune perché -delete implica -depth e -depth rende -prune inefficace.
osserva il comportamento di trova con e senza -depth :
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
Non vi è alcuna garanzia sull'ordine in una singola directory. Ma c'è una garanzia che una directory venga elaborata prima del suo contenuto. Nota foo/ prima di qualsiasi foo/* e foo/bar prima di qualsiasi foo/bar/* .
Questo può essere annullato con -depth .
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Nota che ora tutti i foo/* appaiono prima di foo/ . Lo stesso con foo/bar .
maggiori spiegazioni:
-pruneimpedisce a find di scendere in una directory. In altre parole-prunesalta il contenuto della directory. Nel tuo caso-name b -prunesignifica che quando trova raggiunge una directory con il nomebsalterà la directory comprese tutte le sottodirectory.-depthfa find per elaborare il contenuto di una directory prima della directory stessa. Ciò significa che nel momento in cui find elabora la voce di directorybil suo contenuto è già stato elaborato. Quindi-pruneè inefficace con-depthin vigore.-deleteimplica-depthquindi può eliminare prima il contenuto e poi la directory vuota.-deleterifiuta di eliminare le directory non vuote.
Spiegazione del metodo alternativo:
find a -not -path "*/b*" -type f -delete
Questo potrebbe essere più facile da ricordare o meno.
Questo comando scende ancora nella directory b ed elabora ogni singolo file in esso contenuto solo per -not di respingerli. Questo può essere un problema di prestazioni se la directory b è enorme.
-path funziona in modo diverso da -name . -name corrisponde solo al nome (del file o della directory) mentre -path corrisponde all'intero percorso. Ad esempio, osserva il percorso /home/lesmana/foo/bar . -name bar corrisponderà perché il nome è bar . -path "*/foo*" corrisponderà perché la stringa /foo è nel percorso. -path ha alcune complessità che dovresti capire prima di usarlo. Leggi la pagina man di find per maggiori dettagli.
Attenzione che questo non è infallibile al 100%. Ci sono possibilità di "falsi positivi". Il modo in cui il comando è scritto sopra salterà qualsiasi file che ha una directory padre il cui nome inizia con b (positivo). Ma salterà anche qualsiasi file il cui nome inizia con b indipendentemente dalla posizione nell'albero (falso positivo). Questo può essere risolto scrivendo un'espressione migliore di "*/b*" . Questo è lasciato come esercizio per il lettore.
Presumo che tu abbia usato a e b poiché i segnaposto e i nomi reali sono più simili a allosaurus e brachiosaurus . Se metti brachiosaurus al posto di b quindi la quantità di falsi positivi sarà drasticamente ridotta.
Almeno i falsi positivi saranno non cancellato, quindi non sarà così tragico. Inoltre, puoi verificare la presenza di falsi positivi eseguendo prima il comando senza -delete (ma ricorda di inserire la -depth implicita ) ed esaminare l'output.
find a -not -path "*/b*" -type f -depth