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:
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 -
.
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.