Como executar um alias em um script de shell?

101

Eu tenho um arquivo executável mpiexec, cujo caminho completo é ~/petsc-3.2-p6/petsc-arch/bin/mpiexec. Como desejo executar esse comando em diretórios diferentes (sem precisar redigitar o caminho inteiro), configurei um alias no meu .bashrcarquivo inicial :

alias petsc="~/petsc-3.2-p6/petsc-arch/bin/mpiexec"  

o que me permite executar esse mpiexecarquivo no prompt de comando facilmente, digitando:

petsc myexecutable

Tentei escrever um arquivo de script de shell, nomeado script, usando meu novo alias petsccomo comando. Depois de dar ao meu shell script as permissões apropriadas (usando chmod), tentei executar o script. No entanto, ele me deu o seguinte erro:

./script: line 1: petsc: command not found

Eu sei que eu poderia escrever o caminho completo para o mpiexecarquivo, mas é complicado escrever o caminho completo toda vez que eu quiser escrever um novo script. Existe uma maneira de usar meu alias petscdentro do arquivo de script? Existe uma maneira de editar .bashrcou .bash_profilefazer isso acontecer?

Paulo
fonte
Que tal adicionar o alias para .bash_aliases? Também que tal aliasing o caminho absoluto em vez de caminho relativo comoalias petsc='/home/user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
Nitin Venkatesh
@nitstorm: Nenhuma solução parece funcionar ... Eu ainda obter o mesmo erro como antes
Paul
Relacionados: unix.stackexchange.com/questions/1496/...
AlikElzin-Kilaka

Respostas:

74
  1. No seu script de shell, use o caminho completo em vez de um alias.

  2. No seu script de shell, defina uma sintaxe variável e diferente

    petsc='/home/your_user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
    
    $petsc myexecutable
    
  3. Use uma função no seu script. Provavelmente melhor se petscfor complexo

    function petsc () {
        command 1
        command 2
    }
    
    petsc myexecutable
    
  4. Crie seus aliases

    shopt -s expand_aliases
    source /home/your_user/.bashrc
    

Você provavelmente não deseja obter sua .bashrc, portanto, na IMO, um dos três primeiros seria melhor.

Pantera
fonte
16
O ponto 4 não funciona, a menos que você use shopt -s expand_aliaseso mesmo script.
enzotib
Sua sugestão 2) funciona, mas quero poder usar o mesmo comando em vários scripts de shell sem precisar escrever a primeira linha petsc = "...". Existe uma maneira de fazer isso?
Paul
1
@enzotib - obrigado, eu adicionei isso à minha resposta.
Pantera
1
No ponto 2, você não define um alias, mas uma variável.
Pabouk
1
Não solicitado pelo OP, mas relevante para o título da pergunta: o ponto 2 não funcionará com comandos que contenham |. Aqui, use shopt -s expand_aliases& alias local, por exemplo alias myalias='echo abc|rev'- requer quebra de linha antes do uso (consulte ALIASES em man bash). Ponto 4: o arquivo originado pode impedir a execução não interativa, ou seja, em um script. Procure antecipadamente exitou return, por exemplo, [ -z "$PS1" ] && return(verifica se o prompt principal não está definido, indicando shell não interativo) ou pode haver um check- iin $-( $-contém opções de shell, isignifica interativo). Veja man bashpara essas variáveis.
válido
62

Os aliases foram descontinuados em favor das funções do shell. Na bashpágina do manual:

For almost every purpose, aliases are superseded by shell functions.

Para criar uma função e exportá-la para subshells, coloque o seguinte em seu ~/.bashrc:

petsc() {
    ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
}
export -f petsc

Em seguida, você pode chamar seu comando livremente de seus scripts.

enzotib
fonte
Isso quase funciona ... o único problema é que preciso passar diferentes sinalizadores para o executável "mpiexec" ... Por exemplo, preciso executar algo como "petsc -n 40 myexecutable" com o alias "petsc"
Paul
4
@ Paul: eu adicionei "$@"apenas para lidar com argumentos.
enzotib
12

As funções e aliases do shell são limitados ao shell e não funcionam em scripts de shell executados. Alternativas para o seu caso:

  • (se você não se incomodar em usar em mpiexecvez de petsc) Adicione $HOME/petsc-3.2-p6/petsc-arch/binà sua PATHvariável. Isso pode ser feito editando ~/.profilee anexando:

    PATH="$HOME/petsc-3.2-p6/petsc-arch/bin:$PATH"

    Faça login novamente para aplicar essas alterações

  • Crie o diretório ~/bine

    • crie um script de wrapper chamado petsccontendo:

      #!/bin/sh
      exec ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
      
    • se o programa permitir, você pode pular o shellscript e criar um link simbólico usando o comando:

      ln -s ~/petsc-3.2-p6/petsc-arch/bin/mpiexec ~/bin/petsc
Lekensteyn
fonte
9

No bash 4 você pode usar variável especial: $BASH_ALIASES.

Por exemplo:

$ alias foo="echo test"
$ echo ${BASH_ALIASES[foo]}
echo test
$ echo `${BASH_ALIASES[foo]}` bar
test bar

Alternativamente, defina como variável e use a substituição de comando ou eval.

Por exemplo, em vez de definir o alias, como:

alias foo="echo test"

defina-o como:

foo="echo test"

em vez de. Em seguida, execute-o:

find . -type f -exec sh -c "eval $foo" \;

ou:

find . -type f -exec sh -c "echo `$foo`" \;
kenorb
fonte
Embora aliases sejam descontinuados em favor das funções shell, essa resposta é a única que deve ser aceita. Até o antigo Debian 8 tem a versão 4 do bash, então essa ${BASH_ALIASES[alias]}é uma boa opção. Caso contrário, eu tive que editar muitas linhas dos meus .bash_aliases para aplicar outras coisas. Obrigado.
erm3nda
8

Você pode forçar o bash a executar seu script como um shell interativo com o sinalizador -i. Isso informará o arquivo .bashrc para definir aliases e outras funções.

Exemplo:

~ $ grep ll .bashrc
alias ll='ls -lah'
~ $ cat script.sh 
#!/bin/sh

ll
~ $ bash script.sh 
script.sh: line 3: ll: command not found
~ $ bash -i script.sh
..directory contents..

Mais informações:

$ man bash
Amado Martinez
fonte
2
.bashrcTambém é lido durante a execução do comando SSH não-interativo (é por isso que ele tem um cheque de interatividade no topo)
Muru
6
ALIASES
   ...
   Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see the description of shopt under SHELL BUILTIN COMMANDS
   below).

Portanto, a resposta real para essa pergunta, para quem procura usar aliases reais em scripts de shell em vez de alternativas a eles, é:

#!/bin/bash

shopt -s expand_aliases

alias foo=bar

foo whatever

Quanto ao motivo pelo qual gostaria de fazer isso: devido a circunstâncias incomuns, preciso induzir um Dockerfile a pensar que é um script de shell.

Jogue fora a conta
fonte
4
  1. Em .bash_aliases:

    petsc {
    ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    }
    

    Ou colocar a função na .bashrc. Geralmente, .bashrcapenas as configurações de bashsão armazenadas.

  2. No terminal: source .bash_aliases

  3. Chame-o: petsc arg(s)

Vantagem: você não precisa export -f petscde .bash_aliases. Os aliases foram descontinuados, mas o uso .bash_aliasesde funções está ok.

Timo
fonte
Eu gosto desta solução, vou dar-lhe uma tentativa mais tarde
Greenonline
2
  1. Use seus aliases no seu script de shell.
  2. Crie seu script em seu shell interativo atual, em vez de executá-lo.

Portanto, se você tiver um arquivo chamado script.shcom seus comandos que inclua o uso de aliases, basta digitar:

source script.sh
Gordon Erlebacher
fonte
@DavidFoerster Este método funciona bem. O fornecimento de um script com .ou sourcebuiiltin faz com que o shell atual execute todos os comandos nele. Se a expansão do alias ocorrer no shell em que .ou sourcefor executado, isso ocorrerá. No entanto, é importante perceber que esse método é útil apenas algumas vezes, porque geralmente é necessário ou desejado a execução de um script em seu próprio shell, com seu próprio ambiente. Os scripts de shell escritos com a intenção de serem executados da maneira usual geralmente não devem ser originados - eles geralmente não funcionam corretamente.
Eliah Kagan
@EliahKagan: Obrigado. Agora eu entendo o que a resposta deve significar. Vou adicionar uma explicação.
David Foerster
1

(Edição: funções removidas desde que eu li mal a chamada do mpiexec.)

Se a única coisa que você precisa é menos digitação, por que não coloca a pasta no $ PATH? Ou faça um link simbólico para mpiexec a partir de alguma pasta em $ PATH? Ou (o meu favorito) coloca o alias em um script que você obtém no script de chamada?

sem martelo
fonte
1
A razão pela qual não posso colocá-lo no meu $ PATH é porque tenho outro arquivo 'mpiexec' em outro diretório que já está no meu $ PATH. Se eu adicionar o caminho para esse novo 'mpiexec', ele provavelmente tentará executar os dois ... não seria?
Paul
1
Não consigo entender por que não simplesmente usar "$@".
enzotib
2
Paul, tentará executar o primeiro no PATH, não os dois.
Unhammer #
enzotib, ah eu interpretei errado o modo como o mpiexec foi chamado, achei que precisava de todos os argumentos como um. Vai editar a minha resposta :)
unhammer