¿Por qué mi script Bash no reconoce alias?


216

En mi ~/.bashrcarchivo residen dos definiciones:

  1. commandA, que es un alias para un camino más largo
  2. commandB, que es un alias para un script Bash

Quiero procesar el mismo archivo con estos dos comandos, así que escribí el siguiente script de Bash:


#!/bin/bash

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

Incluso después de cerrar sesión y volver a iniciar sesión, Bash me solicita command not founderrores para ambos comandos cuando ejecuto este script.

¿Qué estoy haciendo mal?


10
Por cierto, no hay necesidad de iniciar y cerrar sesión para que se reconozca un alias. Solo necesitas hacer source ~/.bashrc.
tshepang el

Para mi caso, el agente SSH me conectó de forma remota, después de agregar un alias cuando cerré el agente SSH y me conecté nuevamente, comenzó a funcionar.
dav

Un alias es una forma de acortar un comando. (Solo se usan en shells interactivos y no en scripts; esta es una de las muy pocas diferencias entre un script y un shell interactivo.)
Kris Roofe

Respuestas:


117

En primer lugar, como dijo ddeimeke, los alias por defecto no se expanden en shells no interactivos.

En segundo lugar, .bashrcno es leído por shells no interactivos a menos que establezca la BASH_ENVvariable de entorno.

Pero lo más importante: ¡no hagas eso! ¿Por favor? Un día moverás ese script a algún lugar donde no se establezcan los alias necesarios y se romperá nuevamente.

En su lugar, establezca y use variables de entorno como accesos directos en su secuencia de comandos:

#!/bin/bash

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

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

55
Esa solución no funciona para los aliascasos de uso habituales . Por ej alias mv="mv -v --backup=numbered".
Evi1M4chine

@ Evi1M4chine: Sí, lo hace. Al menos después de revertir la edición innecesaria de Gilles. Pero de todos modos, podría ser mejor usar una variable diferente para los parámetros.

1
Ah, tenga en cuenta la falta de comillas alrededor de $CMDA/ $CMDB... Además de las variables en mayúsculas que se reservan para bash en bash, y de hecho funciona, esa falta de comillas me inquieta mucho ... Gracias de todos modos.
Evi1M4chine

@ Evi1M4chine: ¿Qué? 1. Eliminé las citas en la edición más reciente. 2. ¿De dónde sacas el "reservado para bash"? Esta sería la primera vez que oiría hablar de ella. 3. Si eso te inquieta, ¿cómo te sientes al usar bash en primer lugar? De todos modos, use una variable separada para las opciones como le dije.

1
@alvas: se supone que gizmono está en el camino o que hay un comando con el mismo nombre pero con una prioridad más alta. de lo contrario, podría establecer CMDAsimplemente gizmoen claro en primer lugar.

161

Si observa la página de manual de bash, encontrará:

Los alias no se expanden cuando el shell no es interactivo, a menos que la opción del shell expand_aliases se configure usando shopt (consulte la descripción de shopt en SHELL BUILTIN COMMANDS a continuación).

Así que pon un

shopt -s expand_aliases

en tu guion

Asegúrese de obtener su archivo de alias después de configurar esto en su script.

shopt -s expand_aliases
source ~/.bash_aliases

77
Lo puse en mi script, pero todavía no funciona. Mismo error.
Zaid

55
Agregar shopt -s expand_aliases source ~/.bash_aliasesfunciona perfectamente para mí. A menudo hay una forma de detección de shell interactiva en .bashrc como esta: # If not running interactively, don't do anything [ -z "$PS1" ] && return@Zaid, tal vez desee verificar eso en el archivo que obtuvo.
Frank Schubert

1
¡excelente! salvé mis guiones !! :) es tan difícil leer / buscar / buscar información y páginas de manual en el terminal que me di por vencido hace mucho tiempo y busqué en Internet ...
Aquarius Power

2
Curiosamente, shopt -s expand_aliasesno tiene que ir antes de la definición del alias, sino antes del uso del alias. Agregar a @FrankSchubert: La detección de shell interactivo también se puede hacer usando $-las opciones que contiene el shell, específicamente isi el shell es interactivo.
válido el

2
esta no es una respuesta correcta ... Obtener la fuente de sus alias dentro de su script no es la respuesta. Es ~/.bash_aliasesposible que dependa de otras cosas previamente cargadas en un shell interactivo ... Lo más parecido que encontré fue cambiar su hashbang a #!/bin/bash -liAún no perfecto. Idealmente, debe usar funciones y no alias.
Stefanos Kalantzis

44

Los alias no se pueden exportar, por lo que no están disponibles en scripts de shell en los que no están definidos. En otras palabras, si los define en ~/.bashrcellos, no están disponibles your_script.sh(a menos que se base ~/.bashrcen el script, lo cual no recomendaría, pero hay formas de hacerlo correctamente).

Sin embargo, las funciones se pueden exportar y estarían disponibles para los scripts de shell que se ejecutan desde un entorno en el que se definen. Esto se puede hacer colocando esto en su bashrc:

foo ()
{
    echo "¡Hola Mundo!"
}
export -f foo

Como dice el manual de Bash, "Para casi cualquier propósito, las funciones de shell son preferibles a los alias".


1
Si bien esto técnicamente no responde la pregunta, como usted dice, simplemente puede reemplazar alias commandA=...con commandA() { ... }entonces export commandAy obtiene un comportamiento idéntico al alias. Así que, por lo que sé, esta es una alternativa casi idéntica a los alias que funciona muy bien en los scripts de bash
Phylliida

El problema aquí es cuando necesita un alias al que le pasa muchas opciones citadas. por ejemplo, como ejemplo, alias b=bashhace que sea fácil hacer lo b -c "echo test | grep test"que sería difícil de hacer en funciones.
Fmstrat

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

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

El ies para interactivos y fuentes de su bashperfil para usted.


-5

Descubrí que a veces el script bash tampoco reconoce la exportación. Sin embargo, cambiándolo a

#!/bin/sh

funciona para mi.


1
No, no lo hizo ...
Hafiz Temuri
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.