Um alias é interno ao shell onde está definido. Não é visível para outros processos. O mesmo vale para as funções do shell. xargs é um aplicativo separado, que não é um shell, portanto não possui um conceito de aliases ou funções.
Você pode fazer com que o xargs invoque um shell em vez de invocar grep diretamente. No entanto, apenas invocar um shell não é suficiente, você tem que definir o alias nesse shell também. Se o alias estiver definido em seu .bashrc , você poderá fornecer esse arquivo; no entanto, isso pode não funcionar, pois o .bashrc realiza outras tarefas que não fazem sentido em um shell não interativo.
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E regex_here "$@"' _
Cuidado com os meandros da citação aninhada ao digitar o regexp. Você pode simplificar sua vida passando o regexp como um parâmetro para o shell.
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E "$0" "$@"' regex_here
Você pode executar a pesquisa de alias explicitamente. Então, xargs verá grep -n --color=always .
find . -name '*.py' | xargs "${BASH_ALIASES[grep]}" regex_here
No zsh:
find . -name '*.py' | xargs $aliases[grep] regex_here
A propósito, observe que find … | xargs … quebra em nomes de arquivos contendo espaços (entre outros) . Você pode corrigir isso alterando para registros delimitados por nulo:
find . -name '*.py' -print0 | xargs -0 "${BASH_ALIASES[grep]}" regex_here
ou usando -exec :
find . -name '*.py' -exec "${BASH_ALIASES[grep]}" regex_here {} +
Em vez de chamar find , você pode fazer tudo completamente dentro do shell. O padrão glob **/ atravessa os diretórios recursivamente. No bash, você precisa executar shopt -s globstar para ativar este padrão glob primeiro.
grep regex_here **/*.py
Isso tem algumas limitações:
- Se muitos arquivos corresponderem (ou se tiverem caminhos longos), o comando poderá falhar porque excede o comprimento máximo da linha de comandos.
- No bash ≤4.2 (mas não nas versões mais recentes, nem no ksh ou zsh),
**/recorre a links simbólicos para diretórios.
Outra abordagem é usar a substituição do processo, conforme sugerido pela MariusMatutiae .
grep regex_here <(find . -name '*.py')
Isso é útil quando **/ não é aplicável: para expressões find complexas ou na bash ≤4.2 quando você não deseja recorrer a links simbólicos. Observe que isso quebra em nomes de arquivos contendo espaços; uma solução alternativa é set IFS e desabilitar o globbing , mas está começando a ficar um pouco complexo:
(IFS=$'\n'; set -f; grep regex_here <(find . -name '*.py') )