Parola grep all'interno di un file, quindi copia il file


9

Ho una raccolta di file (* .zip, * .txt, * .tar.gz, * .doc, ... ecc.). Questi file risiedono in un percorso. Voglio trovare tutti i file (* .txt), quindi copiare solo i file di testo che contengono parole specifiche (ad es. LINUX / UNIX).

Ho eseguito il seguente:

find . -name "*.txt" | grep 'LINUX/UNIX'

Questo comando è stato in grado di trovare tutti i file di testo, quindi "grep" ha filtrato i file di testo risultanti elencando solo i file di testo che contengono "LINUX / UNIX".

Come posso copiare questi file finali (ovvero i file di testo che contengono "LINUX / UNIX") in un percorso di scelta specifico?

Ho provato ad applicare xargs

find . -name "*.txt" | grep 'LINUX/UNIX' | xargs cp <to a path>

Ma non ha funzionato


Risposte:


21

Provare:

grep -rl --null --include '*.txt' LINUX/UNIX . | xargs -0r cp -t /path/to/dest

Poiché questo comando utilizza la separazione NUL, è sicuro per tutti i nomi di file, compresi quelli con nomi difficili che includono spazi vuoti, tabulazioni o persino newline.

Quanto sopra richiede GNU cp. Per MacOS / FreeBSD, prova:

grep -rl --null --include '*.txt' LINUX/UNIX . | xargs -0 sh -c 'cp "$@" /path/to/dest' sh

Come funziona:

  1. grep opzioni e argomenti

    • -rdice a grep di cercare ricorsivamente attraverso la struttura delle directory. (Su FreeBSD, -rseguiranno i collegamenti simbolici nelle directory. Questo non è vero né per OS / X né per le versioni recenti di GNU grep.)

    • --include '*.txt'dice a grep di restituire solo i file i cui nomi corrispondono al glob *.txt(inclusi quelli nascosti come .foo.txto .txt).

    • -l dice a grep di restituire solo i nomi dei file corrispondenti, non la corrispondenza stessa.

    • --nulldice a grep di usare i caratteri NUL per separare i nomi dei file. ( --nullÈ supportato da grepsotto GNU / Linux , MacOS e FreeBSD , ma non OpenBSD .)

    • LINUX/UNIX dice a grep di cercare solo i file il cui contenuto include la regex LINUX/UNIX

    • .cerca nella directory corrente. Puoi ometterlo nelle ultime versioni di GNU grep, ma dovrai passare un --terminatore di opzione cpper proteggerti dai nomi di file che iniziano con -.

  2. xargs opzioni e argomenti

    • -0 dice a xargs di aspettarsi un input separato da NUL.

    • -rdice a xargs di non eseguire il comando a meno che non sia stato trovato almeno un file. (Questa opzione non è necessaria su BSD o OSX e non è compatibile con OSX xargs.)

    • cp -t /path/to/destcopia le directory nella directory di destinazione. ( -trichiede GNU cp.)


Per Mac OS X e probabilmente BSD, ti consigliamo di utilizzare --null anziché -Z. Inoltre, penso che cp -tsia solo Linux.
Edward Falk,

1
@EdwardFalk Ottimo punto. Grazie. Ho aggiornato per utilizzare --nulle ho aggiunto una versione per BSD / OSX che non utilizza cp -t.
Giovanni 1024,

@ StéphaneChazelas Grazie per i miglioramenti.
Giovanni 1024,

1
OpenBSD grepnon ha --null.
Kusalananda

@Kusalananda Grazie. Risposta aggiornata per notare che OpenBSD non supporta --null.
Giovanni 1024,

14

Più portabile (solo funzionalità POSIX):

find . -type f -name '*.txt' -exec grep -q LINUX/UNIX {} \; -exec cp {} /path/to/dest \;

3

Il seguente sh / Bash un liner è un altro metodo, anche se funzionerà solo nella directory corrente e non ricorre:

for f in ./*.txt; do if grep -l 'LINUX/UNIX' "$f"; then cp "$f" /path/to/dest/; fi; done

L' -lopzione grep stamperà un elenco dei file che vengono copiati, sebbene tu possa usarlo -qse non vuoi vedere nulla sullo schermo.


0

Non sono sicuro del motivo per cui la stringa originale non ha funzionato. Il seguente comando funziona per me.

trova / -name (nome file *) | grep '(nomefile.extenzione)' | xargs cp -t ./

Nel mio caso il nome file * è una raccolta di file con lo stesso nome con tipi di file diversi (txt, zip, ecc.). Faccio grep per scoprire solo il nomefile.txt e copiarlo nella mia directory di destinazione (che è attualmente, ./).

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.