Por que meu script Bash não reconhece aliases?


216

No meu ~/.bashrcarquivo residem duas definições:

  1. commandA, que é um alias para um caminho mais longo
  2. commandB, que é um alias para um script Bash

Quero processar o mesmo arquivo com esses dois comandos, então escrevi o seguinte script Bash:


#!/bin/bash

for file in "$@"
    do
    commandA $file
    commandB $file
done

Mesmo depois de sair da minha sessão e voltar a entrar, o Bash solicita command not founderros nos dois comandos quando executo esse script.

O que estou fazendo errado?


10
BTW, não é necessário fazer login e logout para ter um alias reconhecido. Você precisa apenas fazer source ~/.bashrc.
— tshepang

No meu caso, fui conectado pelo agente SSH remotamente, depois de adicionar o alias ao fechar o agente SSH e conectar novamente, ele começou a funcionar.
— dav

Um alias é uma maneira de encurtar um comando. (Eles são usados ​​apenas em shells interativos e não em scripts - essa é uma das poucas diferenças entre um script e um shell interativo.)
— Kris Roofe

Respostas:


117

Primeiro, como disse o ddeimeke, os aliases por padrão não são expandidos em shells não interativos.

Segundo, .bashrcnão é lido por shells não interativos, a menos que você defina a BASH_ENVvariável de ambiente.

Mas o mais importante: não faça isso! Por favor? Um dia você moverá esse script para algum lugar onde os aliases necessários não estejam definidos e ele será interrompido novamente.

Em vez disso, defina e use variáveis ​​de ambiente como atalhos no seu script:

#!/bin/bash

CMDA=/path/to/gizmo
CMDB=/path/to/huzzah.sh

for file in "$@"
do
    $CMDA "$file"
    $CMDB "$file"
done

5
Essa solução não funciona nos aliascasos de uso habituais . Por exemplo alias mv="mv -v --backup=numbered".
— Evi1M4chine

@ Evi1M4chine: Sim, faz. Pelo menos depois de reverter a edição desnecessária de Gilles. Mas talvez seja melhor usar uma variável diferente para os parâmetros.

1
Ah, observe a falta de aspas em torno de $CMDA/ $CMDB… Além de as variáveis ​​maiúsculas serem reservadas para o bash em si, e de fato funcionar, essa falta de aspas me deixa muito desconfortável… Obrigado mesmo assim.
— Evi1M4chine

@ Evi1M4chine: Uh, o que? 1. Eu mesmo removi as aspas na edição mais recente. 2. de onde você obtém o "reservado para o próprio bash"? essa seria a primeira vez que ouvi falar disso. 3. Se isso o deixa desconfortável, como você se sente ao usar o bash? De qualquer forma, use uma variável separada para as opções, como eu disse.

1
@ alvas: a suposição é que gizmonão está no caminho ou existe um comando com o mesmo nome, mas com uma prioridade mais alta. caso contrário, você pode simplesmente definir CMDAa planície gizmoem primeiro lugar.

161

Se você olhar para a página de manual do bash, encontrará:

Os aliases não são expandidos quando o shell não é interativo, a menos que a opção do shell expand_aliases seja configurada usando shopt (consulte a descrição do shopt em SHELL BUILTIN COMMANDS abaixo).

Então coloque um

shopt -s expand_aliases

no seu script.

Certifique-se de fornecer o arquivo de aliases depois de configurá-lo no seu script.

shopt -s expand_aliases
source ~/.bash_aliases

7
Coloquei no meu script, mas ainda não está funcionando. Mesmo erro.
— Zaid

5
Adicionar shopt -s expand_aliases source ~/.bash_aliasesfunciona perfeitamente para mim. Frequentemente, existe uma forma de detecção interativa de shell em .bashrc assim: # If not running interactively, don't do anything [ -z "$PS1" ] && return@Zaid, talvez você queira verificar isso no arquivo que você originou.
— precisa

1
excelente! salvou meus scripts !! :) é tão difícil ler / pesquisar / procurar informações e páginas de manual no terminal que eu desisti há muito tempo e procurei na internet ...
— Aquarius Power

2
Curiosamente, shopt -s expand_aliasesnão precisa ir antes da definição do alias, mas antes do uso do alias. Adicionando ao @FrankSchubert: A detecção interativa do shell também pode ser feita usando o $-que contém as opções para o shell, especificamente ise o shell for interativo.
— válido

2
essa não é uma resposta correta ... Fornecer seus apelidos dentro do seu script não é a resposta. Você ~/.bash_aliasespode depender de outras coisas carregadas anteriormente em um shell interativo ... A coisa mais próxima que encontrei foi alterar seu hashbang para #!/bin/bash -liAinda não perfeito. Idealmente, você deve usar funções e não aliases.
— Stefanos Kalantzis

44

Os aliases não podem ser exportados, portanto, não estão disponíveis em scripts de shell nos quais não estão definidos. Em outras palavras, se você os definir, eles ~/.bashrcnão estarão disponíveis your_script.sh(a menos que você forneça ~/.bashrcno script, o que eu não recomendaria, mas existem maneiras de fazer isso corretamente).

No entanto, as funções podem ser exportadas e estariam disponíveis para shell scripts que são executados em um ambiente no qual estão definidas. Isso pode ser feito colocando-o no seu bashrc:

foo ()
{
    eco "Olá, mundo!"
}
export -f foo

Como o manual do Bash diz: "Para quase todos os fins, as funções do shell são preferidas aos aliases".


1
Enquanto isso não tecnicamente responder à pergunta, como você diz, você pode simplesmente substituir alias commandA=...com commandA() { ... }, em seguida, export commandAe você terá um comportamento idêntico ao alias. Portanto, esta é praticamente uma alternativa idêntica à aliases, tanto quanto eu sei que funciona muito bem em bash scripts
— Phylliida

O problema aqui é quando você precisa de um alias ao qual passa muitas opções citadas. por exemplo, como exemplo, alias b=bashfacilita o b -c "echo test | grep test"que seria difícil de executar em funções.
— Fmstrat 13/08

@Fmstrat: b () { bash "$@"; }thenb -c "echo test | grep test"
— Dennis Williamson

11
[cmd line] > bash -i [your script's file path]

O ié para interativo e fornece seu bashperfil para você.


-5

Às vezes, o script bash também não reconhece a exportação. No entanto, alterá-lo para

#!/bin/sh

funciona para mim.


1
Não, não ...
— Hafiz Temuri
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.