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') )