TL; DR: il modo migliore è usare al -exec rmposto di -delete.
find a \( -name b -prune \) -o -type f -exec rm {} +
Spiegazione:
Perché trovare lamentarsi quando si tenta di utilizzare -deletecon -prune?
Risposta breve: perché -deleteimplica -depthe -depthrende -pruneinefficace.
Prima di arrivare alla lunga risposta, osservare innanzitutto il comportamento di find con e senza -depth:
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
Non esiste alcuna garanzia sull'ordine in una singola directory. Ma c'è una garanzia che una directory viene elaborata prima del suo contenuto. Nota foo/prima di qualsiasi foo/*e foo/barprima di qualsiasi foo/bar/*.
Questo può essere invertito con -depth.
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Nota che ora foo/*appaiono tutti prima foo/. Lo stesso con foo/bar.
Risposta più lunga:
-pruneimpedisce a find di scendere in una directory. In altre parole, -prunesalta il contenuto della directory. Nel tuo caso -name b -pruneimpedisce a find di scendere in qualsiasi directory con il nome b.
-depthfa trovare per elaborare il contenuto di una directory prima della directory stessa. Ciò significa che nel momento in cui find riesce a elaborare la voce della directory, il bsuo contenuto è già stato elaborato. Quindi -pruneè inefficace con -depthin effetti.
-deleteimplica -depthquindi in grado di eliminare prima i file e poi la directory vuota. -deletesi rifiuta di eliminare le directory non vuote. Immagino che sarebbe possibile aggiungere un'opzione per forzare -deletel'eliminazione di directory non vuote e / o per impedire -deleteche ciò implichi -depth. Ma questa è un'altra storia.
C'è un altro modo per ottenere ciò che vuoi:
find a -not -path "*/b*" -type f -delete
Questo può essere o non essere più facile da ricordare.
Questo comando scende ancora nella directory be procede ogni singolo file in essa contenuto solo per -notrifiutarli. Questo può essere un problema di prestazioni se la directory bè enorme.
-pathfunziona diversamente da -name. -namecorrisponde solo al nome (del file o della directory) mentre -pathcorrisponde all'intero percorso. Ad esempio osservare il percorso /home/lesmana/foo/bar. -name -barcorrisponderà perché il nome è bar. -path "*/foo*"corrisponderà perché la stringa /fooè nel percorso. -pathha alcune complessità che dovresti capire prima di usarlo. Leggi la pagina man di findper maggiori dettagli.
Attenzione che questo non è sicuro al 100%. Ci sono possibilità di "falsi positivi". Il modo in cui il comando è scritto sopra salterà qualsiasi file che ha una directory padre con il nome che inizia b(positivo). Ma salterà anche qualsiasi file con il nome che inizia con bindipendentemente dalla posizione nella struttura (falso positivo). Questo può essere risolto scrivendo un'espressione migliore di "*/b*". Questo è lasciato come esercizio per il lettore.
Presumo che tu abbia usato ae bcome segnaposto e i nomi reali siano più simili allosauruse brachiosaurus. Se lo metti brachiosaurusal posto di ballora la quantità di falsi positivi verrà drasticamente ridotta.
Almeno i falsi positivi non saranno cancellati, quindi non sarà così tragico. Inoltre, è possibile verificare la presenza di falsi positivi eseguendo prima il comando senza -delete(ma ricordarsi di posizionare l'implicito -depth) ed esaminare l'output.
find a -not -path "*/b*" -type f -depth
atrannea/b?