Ecco un modo per farlo...
find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"
per me, questa soluzione non ha funzionato su un comando exec con find, non so davvero perché, quindi la mia soluzione è
find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;
Spiegazione: uguale a sampson-chen con l'aggiunta di
-prune - ignora il percorso in corso di ...
-o - Quindi, se non c'è corrispondenza, stampa i risultati (elimina le directory e stampa i risultati rimanenti)
18:12 $ mkdir a b c d e
18:13 $ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
18:13 $ find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;
gzip: . is a directory -- ignored
gzip: ./a is a directory -- ignored
gzip: ./b is a directory -- ignored
gzip: ./c is a directory -- ignored
./c/3: 0.0% -- replaced with ./c/3.gz
gzip: ./d is a directory -- ignored
./d/4: 0.0% -- replaced with ./d/4.gz
gzip: ./e is a directory -- ignored
./e/5: 0.0% -- replaced with ./e/5.gz
./e/a: 0.0% -- replaced with ./e/a.gz
./e/b: 0.0% -- replaced with ./e/b.gz
Ecco come puoi specificarlo con find
:
find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"
Spiegazione:
find .
- Avvia la ricerca dalla directory di lavoro corrente (in modo ricorsivo per impostazione predefinita)-type f
- Specificare afind
che desideri solo i file nei risultati-name "*_peaks.bed"
- Cerca i file con il nome che termina con_peaks.bed
! -path "./tmp/*"
- Escludi tutti i risultati il cui percorso inizia con./tmp/
! -path "./scripts/*"
- Escludi anche tutti i risultati il cui percorso inizia con./scripts/
Test della soluzione:
$ mkdir a b c d e
$ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
$ find . -type f ! -path "./a/*" ! -path "./b/*"
./d/4
./c/3
./e/a
./e/b
./e/5
Eri molto vicino, il -name
L'opzione considera solo il nome di base, dove come -path
considera l'intero percorso =)
Usa
find \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
o
find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o -name "*_peaks.bed"
o
find \( -path "./tmp" -path "./scripts" \) ! -prune -o -name "*_peaks.bed"
L'ordine è importante. Valuta da sinistra a destra. Inizia sempre con l'esclusione del percorso.
Spiegazione
Non utilizzare -not
(o !
) per escludere l'intera directory. Usa -prune
.Come spiegato nel manuale:
−prune The primary shall always evaluate as true; it
shall cause find not to descend the current
pathname if it is a directory. If the −depth
primary is specified, the −prune primary shall
have no effect.
e nel manuale GNU find:
-path pattern
[...]
To ignore a whole
directory tree, use -prune rather than checking
every file in the tree.
Infatti, se usi -not -path "./pathname"
,find valuterà l'espressione per ogni nodo sotto "./pathname"
.
le espressioni find sono solo valutazioni di condizioni.
\( \)
- operazioni di gruppo (puoi usare-path "./tmp" -prune -o -path "./scripts" -prune -o
, ma è più dettagliato).-path "./script" -prune
- se-path
restituisce vero ed è una directory, restituisce vero per quella directory e no discendere in esso.-path "./script" ! -prune
- restituisce(-path "./script") AND (! -prune)
. Ripristina il "sempre vero" di Prune in sempre falso. Evita di stampare"./script"
come corrispondenza.-path "./script" -prune -false
- da-prune
restituisce sempre true, puoi seguirlo con-false
fare lo stesso di!
.-o
- Operatore OR. Se non viene specificato alcun operatore tra due espressioni, il valore predefinito è l'operatore AND.
Quindi, \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
è espanso in:
[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )
La stampa è importante qui perché senza di essa viene espansa a:
{ [ (-path "./tmp" OR -path "./script" ) AND -prune ] OR (-name "*_peaks.bed" ) } AND print
-print
viene aggiunto da find - ecco perché la maggior parte delle volte non è necessario aggiungerlo nella tua espressione. E poiché -prune
restituisce vero, stamperà "./script" e "./tmp".
Non è necessario negli altri perché abbiamo cambiato -prune
per restituire sempre false.
Suggerimento:puoi usare find -D opt expr 2>&1 1>/dev/null
per vedere come è ottimizzato e ampliato,
find -D search expr 2>&1 1>/dev/null
per vedere quale percorso è controllato.