Grep mot dans un file puis copyz le file

J'ai une collection de files (* .zip, * .txt, * .tar.gz, * .doc, … etc). Ces files résident dans un path. Je veux find tous les files (* .txt), puis copyr uniquement les files text qui contiennent des mots spécifiques (par exemple LINUX / UNIX).

J'ai couru ce qui suit:

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

Cette command a été capable de find tous les files text, puis "grep" a filtré les files text résultants en listant uniquement les files text contenant "LINUX / UNIX".

Comment puis-je copyr ces files finaux (c'est-à-dire les files text contenant «LINUX / UNIX») vers un path spécifique de choix?

J'ai essayé d'appliquer xargs

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

Mais ça n'a pas marché

Essayer:

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

Comme cette command utilise la séparation NUL, elle est sûre pour tous les noms de files, y compris ceux dont les noms sont difficiles, y compris les blancs, les tabulations ou même les returns à la ligne.

Ce qui précède nécessite GNU cp . Pour BSD / OSX, essayez:

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

Comment ça marche:

  1. Options et arguments grep

    • -r request à grep de searchr récursivement à travers la structure de directory. (Sur FreeBSD, -r suivra les liens symboliques dans les directorys, ce qui n'est pas le cas pour OS / X ou les versions récentes de GNU grep ).

    • --include '*.txt' indique à grep de ne renvoyer que les files dont les noms correspondent à glob *.txt (y compris les *.txt cachés comme .foo.txt ou .txt ).

    • -l indique à grep de ne renvoyer que les noms des files correspondants, pas la correspondance elle-même.

    • --null indique à grep d'utiliser des caractères NUL pour séparer les noms de files.

    • LINUX/UNIX indique à grep de ne searchr que les files dont le contenu inclut la regex LINUX/UNIX

    • . searchr dans le directory actuel. Vous pouvez l'omettre dans les versions récentes de GNU grep , mais vous devrez passer un -- terminateur d'option à cp pour se prémunir contre les noms de files qui commencent par - .

  2. Options et arguments xargs

    • -0 request à xargs de s'attendre à une input séparée par NUL.

    • -r request à xargs de ne pas exécuter la command sauf si au less un file a été trouvé. (Cette option n'est pas nécessaire sur BSD ou OSX et n'est pas compatible avec les xargs d'OSX.)

    • cp -t /path/to/dest copy les directorys dans le directory cible. ( -t nécessite GNU cp .)

Plus portable (fonctionnalités POSIX uniquement):

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

Le sh / Bash one liner suivant est une autre méthode, mais ne fonctionnera que dans le directory courant, et ne récursif:

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

L'option -l de grep imprimera une list des files qui sont copiés, bien que vous puissiez utiliser -q si vous ne voulez rien voir à l'écran.