Un alias est interne au shell où il est défini. Il n'est pas visible pour les autres processus. Il en va de même pour les fonctions shell. xargs
est une application distincte, qui n'est pas un shell, donc n'a pas de concept d'alias ou de fonctions.
Vous pouvez faire en sorte que xargs invoque un shell au lieu d'invoquer grep
directement. Cependant, l'invocation d'un shell ne suffit pas, vous devez également définir l'alias dans ce shell. Si l'alias est défini dans votre .bashrc
, vous pouvez source ce fichier; cependant, cela peut ne pas fonctionner, vous .bashrc
effectuez d'autres tâches qui n'ont pas de sens dans un shell non interactif.
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E regex_here "$@"' _
Méfiez-vous des subtilités des citations imbriquées lors de la frappe de l'expression rationnelle. Vous pouvez simplifier votre vie en passant l'expression rationnelle en tant que paramètre au shell.
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E "$0" "$@"' regex_here
Vous pouvez effectuer la recherche d'alias de manière explicite. Alors xargs
verra grep -n --color=always
.
find . -name '*.py' | xargs "${BASH_ALIASES[grep]}" regex_here
En zsh:
find . -name '*.py' | xargs $aliases[grep] regex_here
Soit dit en passant, il se find … | xargs …
casse les noms de fichiers contenant des espaces (entre autres) . Vous pouvez résoudre ce problème en modifiant les enregistrements délimités par des valeurs nulles:
find . -name '*.py' -print0 | xargs -0 "${BASH_ALIASES[grep]}" regex_here
ou en utilisant -exec
:
find . -name '*.py' -exec "${BASH_ALIASES[grep]}" regex_here {} +
Au lieu d'appeler find
, vous pouvez tout faire entièrement à l'intérieur du shell. Le modèle glob **/
parcourt les répertoires de manière récursive. Dans bash, vous devez d'abord exécuter shopt -s globstar
ce modèle global.
grep regex_here **/*.py
Cela a quelques limitations:
- Si un grand nombre de fichiers correspondent (ou s'ils ont de longs chemins d'accès), la commande peut échouer car elle dépasse la longueur de ligne de commande maximale.
- En bash ≤4,2 (mais pas dans les versions plus récentes, ni dans ksh ou zsh), se
**/
reproduit en liens symboliques vers des répertoires.
Une autre approche consiste à utiliser la substitution de processus, comme suggéré par MariusMatutiae .
grep regex_here <(find . -name '*.py')
Ceci est utile lorsque cela **/
ne s'applique pas: pour les find
expressions complexes , ou en bash ≤4,2 lorsque vous ne voulez pas récuser sous des liens symboliques. Notez que cela rompt sur les noms de fichiers contenant des espaces; une solution consiste à définir IFS
et désactiver la globalisation , mais cela commence à devenir un peu complexe:
(IFS=$'\n'; set -f; grep regex_here <(find . -name '*.py') )