¿Cómo ejecutar un alias en un script de shell?

101

Tengo un archivo ejecutable mpiexec, cuya ruta completa es ~/petsc-3.2-p6/petsc-arch/bin/mpiexec. Como quiero ejecutar este comando en diferentes directorios (sin tener que volver a escribir la ruta completa), configuro un alias en mi .bashrcarchivo de inicio :

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

lo que me permite ejecutar este mpiexecarchivo en el símbolo del sistema fácilmente escribiendo:

petsc myexecutable

Traté de escribir un archivo de script de shell, llamado script, usando mi nuevo alias petsccomo comando. Después de otorgarle a mi script de shell los permisos apropiados (usando chmod), intenté ejecutar el script. Sin embargo, me dio el siguiente error:

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

Sé que podría escribir la ruta completa al mpiexecarchivo, pero es engorroso escribir la ruta completa cada vez que quiero escribir un nuevo script. ¿Hay alguna manera de que pueda usar mi alias petscdentro del archivo de script? ¿Hay alguna manera de editar mi .bashrco .bash_profilehacer que esto suceda?

Pablo
fuente
¿Qué tal agregar el alias .bash_aliases? Además, ¿qué tal aliasing la ruta absoluta en lugar de la ruta relativa comoalias petsc='/home/user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
Nitin Venkatesh
@nitstorm: Ninguna de las soluciones parece funcionar ... Todavía recibo el mismo error que antes
Paul
Relacionado: unix.stackexchange.com/questions/1496/…
AlikElzin-kilaka

Respuestas:

74
  1. En su script de shell, use la ruta completa en lugar de un alias.

  2. En su script de shell, establezca una sintaxis diferente y variable

    petsc='/home/your_user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
    
    $petsc myexecutable
  3. Usa una función en tu script. Probablemente mejor si petsces complejo

    function petsc () {
        command 1
        command 2
    }
    
    petsc myexecutable
  4. Busca tus alias

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

Probablemente no desee obtener su fuente .bashrc, por lo tanto, en mi opinión, uno de los primeros 3 sería mejor.

Pantera
fuente
16
El punto 4 no funciona, a menos que lo use shopt -s expand_aliasesen el mismo script.
enzotib
Su sugerencia 2) funciona, pero quiero poder usar el mismo comando en varios scripts de shell sin tener que escribir la primera línea petsc = "...". ¿Hay alguna forma de hacer esto?
Paul
1
@enzotib - gracias, agregué eso a mi respuesta.
Pantera
1
En el punto 2 no establece un alias sino una variable.
Pabouk
1
OP no lo solicita, pero es relevante para el título de la pregunta: el punto 2 no funcionará con comandos que contengan |. Aquí, use shopt -s expand_aliases& alias local, por ejemplo alias myalias='echo abc|rev', requiere un salto de línea antes del uso (vea ALIAS en man bash). Punto 4: el archivo de origen puede evitar la ejecución no interactiva, es decir, en un script. Busque temprano exito return, por ejemplo, [ -z "$PS1" ] && return(verifica si el indicador primario no está configurado para indicar un shell no interactivo) o puede haber un check iin $-( $-contiene opciones de shell, isignifica interactivo). Ver man bashpara esas variables.
válido el
62

Los alias están en desuso a favor de las funciones de shell. Desde la bashpágina del manual:

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

Para crear una función y exportarla a subcapas, coloque lo siguiente en su ~/.bashrc:

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

Entonces puedes llamar libremente a tu comando desde tus scripts.

enzotib
fuente
Eso casi funciona ... el único problema es que necesito poder pasar diferentes banderas al ejecutable "mpiexec" ... Por ejemplo, necesito poder ejecutar algo como "petsc -n 40 myexecutable" con el alias "petsc"
Paul
44
@Paul: agregué "$@"solo para manejar argumentos.
enzotib
12

Las funciones y los alias de Shell están limitados al shell y no funcionan en scripts de shell ejecutados. Alternativas para su caso:

  • (si no se molesta en usar en mpiexeclugar de petsc) Agregue $HOME/petsc-3.2-p6/petsc-arch/bina su PATHvariable. Esto se puede hacer editando ~/.profiley agregando:

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

    Vuelva a iniciar sesión para aplicar estos cambios

  • Crea el directorio ~/biny

    • crear un script de envoltorio llamado que petsccontenga:

      #!/bin/sh
      exec ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    • Si el programa lo permite, puede omitir el shellscript y crear un enlace simbólico con el comando:

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

En bash 4 se puede utilizar variable especial: $BASH_ALIASES.

Por ejemplo:

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

Alternativamente, defínalo como variable y luego usa la sustitución de comandos o eval.

Entonces, por ejemplo, en lugar de definir el alias como:

alias foo="echo test"

definirlo como:

foo="echo test"

en lugar. Luego ejecútelo:

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

o:

find . -type f -exec sh -c "echo `$foo`" \;
kenorb
fuente
Aunque los alias están en desuso en favor de las funciones de shell, esta respuesta es la única que debe aceptarse. Incluso el antiguo Debian 8 tiene la versión 4 de bash, por lo que ${BASH_ALIASES[alias]}es una buena opción. De lo contrario, tuve que editar muchas líneas de mis .bash_aliases para aplicar otras cosas. Gracias.
erm3nda
8

Puede forzar a bash a ejecutar su script como un shell interactivo con el indicador -i. Esto le indicará a su archivo .bashrc que defina alias y otras funciones.

Ejemplo:

~ $ 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..

Más información:

$ man bash
Amado Martinez
fuente
2
.bashrctambién se lee durante la ejecución de comandos SSH no interactivos (es por eso que tiene una verificación de interactividad en la parte superior)
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).

Entonces, la respuesta real a esta pregunta, para aquellos que buscan usar alias reales en scripts de shell en lugar de alternativas a ellos, es:

#!/bin/bash

shopt -s expand_aliases

alias foo=bar

foo whatever

En cuanto a por qué me gustaría hacer esto: debido a circunstancias inusuales, necesito engañar a un Dockerfile para que piense que es un script de shell.

Tirar cuenta
fuente
4
  1. En .bash_aliases:

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

    O poner la función en .bashrc. Por lo general, .bashrcsolo bashse almacenan las configuraciones de configuración .

  2. En terminal: source .bash_aliases

  3. Llámalo: petsc arg(s)

Ventaja: no necesita export -f petscen .bash_aliases. Los alias están en desuso, pero usar las .bash_aliasesfunciones está bien.

Timo
fuente
Me gusta esta solución, la probaré más tarde
Greenonline
2
  1. Use sus alias en su script de shell.
  2. Obtenga su script en su shell actual e interactivo en lugar de ejecutarlo.

Entonces, si tiene un archivo llamado script.shcon sus comandos que incluyen el uso de alias, simplemente escriba:

source script.sh
Gordon Erlebacher
fuente
@DavidFoerster Este método funciona bien. Obtener un script con .o sourcebuiiltin hace que el shell actual ejecute todos los comandos en él. Si se produciría la expansión de alias en la cáscara en la que .o sourcees ejecutado, se produce. Sin embargo, es importante darse cuenta de que este método solo es útil algunas veces, porque a menudo uno necesita o quiere ejecutar un script en su propio shell, con su propio entorno. Las secuencias de comandos de Shell escritas con la intención de ejecutarse de la manera habitual generalmente no deben obtenerse en su lugar; a menudo no funcionan correctamente.
Eliah Kagan
@EliahKagan: Gracias. Ahora entiendo lo que se supone que significa la respuesta. Agregaré una explicación.
David Foerster
1

(EDITAR: funciones eliminadas ya que leí mal la llamada de mpiexec.)

Si lo único que necesita es escribir menos, ¿por qué no coloca la carpeta en $ PATH? ¿O hacer un enlace simbólico a mpiexec desde alguna carpeta en $ PATH? ¿O (mi favorito) pone el alias en un script que usted obtiene en el script de llamada?

desarmar
fuente
1
La razón por la que no puedo ponerlo en mi $ PATH es porque tengo otro archivo 'mpiexec' en otro directorio que ya está en mi $ PATH. Si agrego la ruta a este nuevo 'mpiexec', probablemente intente ejecutarlos a ambos ... ¿no?
Paul
1
No puedo entender por qué no simplemente usar "$@".
enzotib
2
Paul, intentará ejecutar el primero en la RUTA, no ambos.
Martillo
enzotib, ah, leí mal la forma en que se llamaba mpiexec, pensé que necesitaba todos los argumentos como uno.
Editaré