Bash 4.2 no CentOS 6.5:
No meu ~/.bash_profile
eu tenho um monte de aliases, incluindo:
alias grep='grep -n --color=always'
para que eu possa obter destaque de cores e imprimir números de linha automaticamente ao executar grep
. Se eu executar o seguinte, o destaque funcionará conforme o esperado:
$ grep -Re 'regex_here' *.py
No entanto, quando eu executei isso recentemente:
$ find . -name '*.py' | xargs grep -E 'regex_here'
os resultados não foram destacados e os números de linha não foram impressos, forçando-me a voltar e adicionar explicitamente -n --color=always
ao grep
comando.
- Não
xargs
lê aliases no ambiente? - Se não, existe uma maneira de fazer isso?
xargs
comando. O que estou tentando descobrir é se existe uma maneira de chamar diretamente meu apelidoxargs
.export GREP_OPTIONS='-n --color=always'
antes do seu comando xargs?.bash_profile
. Sinta-se livre para escrever uma resposta ...Respostas:
Um alias é interno ao shell em que está definido. Não é visível para outros processos. O mesmo vale para funções de shell.
xargs
é um aplicativo separado, que não é um shell, portanto não possui um conceito de alias ou funções.Você pode fazer xargs chamar um shell em vez de chamar
grep
diretamente. No entanto, apenas invocar um shell não é suficiente, você precisa definir o alias nesse shell também. Se o alias estiver definido no seu.bashrc
, você pode obter esse arquivo; no entanto, isso pode não funcionar, você.bashrc
realiza outras tarefas que não fazem sentido em um shell não interativo.Cuidado com os meandros da cotação aninhada ao digitar a regexp. Você pode simplificar sua vida passando o regexp como um parâmetro para o shell.
Você pode executar a pesquisa de alias explicitamente. Então
xargs
vai vergrep -n --color=always
.No zsh:
A propósito, observe que
find … | xargs …
quebras nos nomes de arquivos que contêm espaços (entre outros) . Você pode corrigir isso alterando para registros delimitados por nulo:ou usando
-exec
:Em vez de ligar
find
, você pode fazer tudo inteiramente dentro do shell. O padrão glob**/
percorre diretórios recursivamente. No bash, você precisa executarshopt -s globstar
para ativar esse padrão glob primeiro.Isso tem algumas limitações:
**/
em links simbólicos para diretórios.Outra abordagem é usar a substituição de processos, conforme sugerido por MariusMatutiae .
Isso é útil quando
**/
não é aplicável: parafind
expressões complexas ou no bash ≤4.2 quando você não deseja se recuperar sob links simbólicos. Observe que isso quebra nos nomes de arquivos que contêm espaços; uma solução alternativa é definirIFS
e desativar o globbing , mas está começando a ficar um pouco complexo:fonte
Usar
alias xargs='xargs '
fonte
sudo
…Por favor, tome isso como uma demonstração de outra abordagem, que não consigo encontrar no pergunta SO :
Você pode escrever uma função de invólucro para
xargs
qual verifica se o primeiro argumento é um alias e, se houver, expanda-o de acordo.Aqui está um código que faz exatamente isso, mas infelizmente requer o shell Z e, portanto, não roda 1: 1 com o bash (e, francamente, eu não estou acostumado com o bash o suficiente para portá-lo):
Prova de que funciona:
fonte
Uma solução mais simples e elegante é usar a substituição de processo :
Ele não cria um novo shell como o pipe, o que significa que você ainda está no shell original onde o alias está definido e a saída é exatamente o que você deseja que seja.
Apenas tome cuidado para não deixar espaço entre o redirecionamento e os parênteses, caso contrário o bash gerará um erro. Que eu saiba, a substituição do processo é suportada por Bash, Zsh, Ksh {88,93}, mas não por pdksh (disseram-me que ainda não deve ser ).
fonte
find
comandos complexos , embora você precise tomar cuidado para que ele se quebre em espaços e que não possa ser corrigido da maneira mais fácilfind | xargs
possível (alternando para-print0
e-0
ou usando-exec
). Quando aplicável,**/
é mais simples e mais robusto.O grep lerá um conjunto de opções padrão da variável de ambiente GREP_OPTIONS. Se você vai colocar
no seu .bashrc, a variável será transferida para os subshells e você obterá os resultados esperados.
fonte
--line-number
ou--color=always
emGREP_OPTIONS
menos que seja apenas para um comando, isso vai quebrar um monte de scripts.--color=auto
é bom ter lá, e isso é tudo. Colocar essa linha no seu.bashrc
vai quebrar muitas coisas./etc/init.d/cron
no meu sistema:value=`egrep "^${var}=" "$ENV_FILE" | tail -n1 | cut -d= -f2`
. Ou a partir de/usr/bin/pdfjam
:pdftitl=`printf "%s" "$PDFinfo" | grep -e … | sed -e …`
. Um alias não é um problema, pois não é visto em scripts.GREP_OPTIONS
muito a previsibilidade das quebras, exceto por algumas opções--color=auto
( como foi para isso que foi projetado).