GNU/Linux >> Linux Esercitazione >  >> Linux

Usa il comando find ma escludi i file in due directory

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 a find 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.


Linux
  1. Trova file e directory su Linux con il comando find

  2. Come scoprire le directory e i file principali (spazio su disco) in Linux

  3. Come utilizzare il comando Grep per trovare testo nei file

  4. Trova i file o le directory più grandi?

  5. Escludere un elenco di directory da Unix Find Command?

Grep Command in Linux (Trova testo nei file)

Come utilizzare il comando cp per copiare file e directory

Come utilizzare il comando SCP per trasferire file

Come escludere una directory durante la ricerca di file in Linux

Trova facilmente file e directory su Linux

Come scoprire le directory o i file che consumano più spazio?