Pourquoi mon script Bash ne reconnaît-il pas les alias?

216

Dans mon ~/.bashrcfichier résident deux définitions:

  1. commandA, qui est un alias pour un chemin plus long
  2. commandB, qui est un alias pour un script Bash

Je veux traiter le même fichier avec ces deux commandes, j'ai donc écrit le script Bash suivant:


#!/bin/bash

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

Même après la déconnexion de ma session et la reconnexion, Bash m'informe des command not founderreurs pour les deux commandes lorsque j'exécute ce script.

Qu'est-ce que je fais mal?

Zaid
la source
10
Par ailleurs, il n'est pas nécessaire de se connecter et de se déconnecter pour faire reconnaître un alias. Vous avez juste besoin de faire source ~/.bashrc.
Tshepang
Dans mon cas, j'étais connecté par un agent SSH à distance, après avoir ajouté un alias lorsque j'ai fermé l'agent SSH et que je me suis reconnecté, il a commencé à fonctionner.
dav
Un alias est un moyen de raccourcir une commande. (Ils ne sont utilisés que dans les shells interactifs et non dans les scripts - c'est l'une des rares différences entre un script et un shell interactif.)
Kris Roofe

Réponses:

117

Tout d’abord, comme l’a dit Ddeimeke, les alias par défaut ne sont pas développés dans des shells non interactifs.

Deuxièmement, il .bashrcn'est pas lu par les shells non interactifs, sauf si vous définissez la BASH_ENVvariable d'environnement.

Mais le plus important: ne faites pas ça! S'il vous plaît? Un jour, vous déplacerez ce script à un endroit où les alias nécessaires ne sont pas définis et il se brisera à nouveau.

A la place, définissez et utilisez des variables d’environnement comme raccourcis dans votre script:

#!/bin/bash

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

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

la source
5
Cette solution ne fonctionne pas pour les aliascas d'utilisation habituels . Par exemple alias mv="mv -v --backup=numbered".
Evi1M4chine
@ Evi1M4chine: Oui, c'est le cas. Au moins après avoir annulé la modification inutile de Gilles. Mais il serait peut-être préférable d'utiliser une variable différente pour les paramètres, de toute façon.
1
Ah, remarquez le manque de guillemets autour de $CMDA/ $CMDB… Hormis les variables majuscules réservées à bash lui-même, et ça marche, ce manque de guillemets me met vraiment mal à l'aise… Merci quand même.
Evi1M4chine
@ Evi1M4chine: Euh quoi? 1. J'ai supprimé les citations moi-même dans l'édition la plus récente. 2. Où trouvez-vous le "réservé à bash"? ce serait la première fois que j'en entends parler. 3. Si cela vous rend mal à l'aise, que pensez-vous de l'utilisation de bash en premier lieu? Quoi qu'il en soit, utilisez une variable distincte pour les options comme je vous l'ai dit.
1
@alvas: l'hypothèse est que ce gizmon'est pas sur le chemin ou il y a une commande avec le même nom mais une priorité plus haute. sinon, vous pouvez simplement mettre CMDAen clair gizmoen premier lieu.
161

Si vous regardez dans la page de manuel bash, vous trouverez:

Les alias ne sont pas développés lorsque le shell n'est pas interactif, sauf si l'option shell expand_aliases est définie à l'aide de shopt (voir la description de shopt sous SHELL BUILTIN COMMANDS ci-dessous).

Alors mettez un

shopt -s expand_aliases

dans votre script.

Assurez-vous d’avoir source votre fichier d’alias après l’avoir défini dans votre script.

shopt -s expand_aliases
source ~/.bash_aliases
Ddeimeke
la source
7
Je l'ai placé dans mon script, mais cela ne fonctionne toujours pas. Même erreur.
Zaid
5
L'ajout shopt -s expand_aliases source ~/.bash_aliasesfonctionne parfaitement pour moi. Il existe souvent une forme de détection de shell interactive dans .bashrc telle que celle-ci: # If not running interactively, don't do anything [ -z "$PS1" ] && return@Zaid, vous souhaiterez peut-être vérifier cela dans le fichier que vous avez acheté.
Frank Schubert
1
excellent! sauvé mes scripts !! :) il est si difficile de lire / rechercher / parcourir les informations et les pages de manuel dans le terminal que je viens d'abandonner il y a longtemps et de rechercher sur Internet ...
Aquarius Power
2
Curieusement, il shopt -s expand_aliasesn'est pas nécessaire d'aller avant la définition du pseudonyme, mais avant son utilisation. Ajout à @FrankSchubert: La détection de shell interactif peut également être effectuée en utilisant $-les options du shell, en particulier isi le shell est interactif.
Valide
2
ce n'est pas une réponse correcte ... La recherche de vos alias dans votre script n'est pas la réponse. Vous ~/.bash_aliasespourriez dépendre d’autres éléments déjà chargés sur un shell interactif ... La chose la plus proche que j’ai trouvée est de changer votre hashbang en #!/bin/bash -liToujours pas parfait. Idéalement, vous devriez utiliser des fonctions et non des alias.
Stefanos Kalantzis
44

Les alias ne peuvent pas être exportés, ils ne sont donc pas disponibles dans les scripts shell dans lesquels ils ne sont pas définis. En d'autres termes, si vous les définissez dans ~/.bashrcils ne sont pas disponibles your_script.sh(sauf si vous indiquez ~/.bashrcdans le script, ce que je ne recommanderais pas, mais il existe des moyens de le faire correctement).

Toutefois, les fonctions peuvent être exportées et seraient disponibles pour les scripts shell exécutés à partir d'un environnement dans lequel ils sont définis. Cela peut être fait en plaçant ceci dans votre bashrc:

foo ()
{
    echo "Bonjour le monde!"
}
exportation

Comme le dit le manuel de Bash, "Dans presque tous les cas, les fonctions du shell sont préférées aux alias".

Dennis Williamson
la source
1
Bien que cela ne réponde pas techniquement à la question, comme vous dites, vous pouvez simplement remplacer alias commandA=...par commandA() { ... }alors export commandAet vous obtenez un comportement identique à celui de l’alias. Donc, c'est à peu près une alternative identique aux pseudonymes, pour autant que je sache, qui fonctionne très bien avec les scripts bash
Phylliida,
Le problème ici est lorsque vous avez besoin d'un alias auquel vous transmettez beaucoup d'options citées. par exemple, à titre d'exemple, alias b=bashil est facile de faire b -c "echo test | grep test"ce qui serait difficile à faire dans les fonctions.
Fmstrat
@Fmstrat: b () { bash "$@"; }thenb -c "echo test | grep test"
Dennis Williamson
11
[cmd line] > bash -i [your script's file path]

Le iest pour interactif et sources votre bashprofil pour vous.

utilisateur65576
la source
-5

J'ai trouvé que parfois, le script bash ne reconnaît pas l'exportation non plus. Cependant, le changer pour

#!/bin/sh

travaille pour moi.

lwpro2
la source
1
Non, ça n'a pas été ...
Hafiz Temuri