Comment utiliser un tuyau dans le paramètre exec pour une commande de recherche?
Question
J'essaie de créer une commande de recherche pour traiter un groupe de fichiers dans un répertoire à l'aide de deux exécutables différents. Malheureusement, -exec
sur find ne permet pas d’utiliser un pipe ou même \|
car le shell interprète ce caractère en premier.
Voici ce que j'essaie de faire (ce qui ne fonctionne pas car la commande de recherche met fin à la recherche):
find /path/to/jpgs -type f -exec jhead -v {} | grep 123 \; -print
La solution
Essayez ceci
find /path/to/jpgs -type f -exec sh -c 'jhead -v {} | grep 123' \; -print
Vous pouvez également essayer d'incorporer votre instruction exec dans un script sh, puis:
find -exec some_script {} \;
Autres conseils
Une approche légèrement différente consisterait à utiliser xargs:
find /path/to/jpgs -type f -print0 | xargs -0 jhead -v | grep 123
que j'ai toujours trouvé un peu plus facile à comprendre et à adapter (les arguments -print0 et -0 sont nécessaires pour faire face aux noms de fichiers contenant des blancs)
Cela pourrait (non testé) être plus efficace que d'utiliser -exec car il dirigera la liste des fichiers vers xargs et xargs garantit que la ligne de commande jhead ne soit pas trop longue.
Avec -exec
, vous ne pouvez exécuter qu'un seul exécutable avec certains arguments et non des commandes shell arbitraires. Pour contourner ce problème, vous pouvez utiliser sh -c '<shell command>'
.
Notez que l'utilisation de grep
est assez inefficace. Pour chaque fichier trouvé, la commande doit être exécutée à nouveau. Ce serait plus efficace si vous pouviez éviter cela. (Par exemple, en déplaçant find
en dehors de xargs
ou en dirigeant les résultats de <=> vers <=> comme suggéré par Palmin .)
Utiliser la commande find
pour ce type de tâche n’est peut-être pas la meilleure alternative. J'utilise fréquemment la commande suivante pour trouver des fichiers contenant les informations demandées:
for i in dist/*.jar; do echo ">> $i"; jar -tf "$i" | grep BeanException; done
Comme cela génère une liste, ne voudriez-vous pas:
find /path/to/jpgs -type f -exec jhead -v {} \; | grep 123
ou
find /path/to/jpgs -type f -print -exec jhead -v {} \; | grep 123
Mettez votre grep sur les résultats de find -exec.
Vous pouvez le faire d’une autre manière, mais c’est aussi un joli ghetto.
En utilisant l'option shell extquote, vous pouvez faire quelque chose de similaire à ceci afin de créer des commandes find, puis de les diriger vers sh.
root@ifrit findtest # find -type f -exec echo ls $"|" cat \;|sh
filename
root@ifrit findtest # find -type f -exec echo ls $"|" cat $"|" xargs cat\;|sh
h
Je pensais juste ajouter que parce que, du moins, la façon dont je l'ai visualisé était plus proche de la question initiale du PO, à savoir utiliser des tuyaux dans exec.