Comment exécuter un alias dans un script shell?


101

J'ai un fichier exécutable mpiexec, dont le chemin complet est ~/petsc-3.2-p6/petsc-arch/bin/mpiexec. Puisque je veux exécuter cette commande dans différents répertoires (sans avoir à ressaisir le chemin complet), j'ai créé un alias dans mon .bashrcfichier personnel:

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

ce qui me permet d’exécuter mpiexecfacilement ce fichier à l’invite de commande en tapant:

petsc myexecutable

J'ai essayé d'écrire un fichier de script shell, nommé script, en utilisant mon nouvel alias petsccomme commande. Après avoir donné à mon script shell les autorisations appropriées (utilisation chmod), j'ai essayé de l'exécuter. Cependant, cela m'a donné l'erreur suivante:

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

Je sais que je pourrais simplement écrire le chemin complet du mpiexecfichier, mais il est fastidieux d’écrire le chemin complet à chaque fois que je veux écrire un nouveau script. Est-il possible d'utiliser mon alias petscdans le fichier de script? Existe-t-il un moyen de modifier mon .bashrcou .bash_profilepour que cela se produise?


Que diriez-vous d'ajouter l'alias à .bash_aliases? Aussi que diriez-vous d'aliasing le chemin absolu au lieu du chemin relatif commealias petsc='/home/user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
Nitin Venkatesh

@nitstorm: Aucune solution ne semble fonctionner ... J'ai toujours la même erreur qu'avant
Paul

Réponses:


74
  1. Dans votre script, utilisez le chemin complet plutôt qu'un alias.

  2. Dans votre script shell, définissez une variable, une syntaxe différente

    petsc='/home/your_user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
    
    $petsc myexecutable
  3. Utilisez une fonction dans votre script. Probablement mieux si petscest complexe

    function petsc () {
        command 1
        command 2
    }
    
    petsc myexecutable
  4. Source vos alias

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

Vous ne voulez probablement pas .bashrctrouver votre source , alors, IMO, un des 3 premiers serait préférable.


16
Le point 4 ne fonctionne pas, sauf si vous utilisez shopt -s expand_aliasesle même script.
enzotib

Votre suggestion 2) fonctionne, mais je veux pouvoir utiliser la même commande dans plusieurs scripts de shell sans avoir à écrire la première ligne petsc = "...". Y a-t-il un moyen de faire cela?
Paul

1
@enzotib - merci, j'ai ajouté cela à ma réponse.
Panthère

1
Au point 2, vous ne définissez pas un alias mais une variable.
Pabouk

1
Non demandé par l'OP mais pertinent pour le titre de la question: le point 2 ne fonctionnera pas avec les commandes contenant |. Ici, use shopt -s expand_aliases& local alias, par exemple alias myalias='echo abc|rev'- nécessite une rupture de ligne avant utilisation (voir ALIASES dans man bash). Point 4: Le fichier généré peut empêcher une exécution non interactive, c'est-à-dire dans un script. Recherchez tôt exitou return, par exemple [ -z "$PS1" ] && return(vérifie si l'invite principale n'est pas définie indiquant un shell non interactif) ou s'il peut y avoir une vérification idans $-( $-contient des options de shell, isignifie interactif). Voir man bashpour ces variables.
Valide

62

Les alias sont déconseillés au profit des fonctions du shell. De la bashpage de manuel:

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

Pour créer une fonction et l'exporter en sous-shell, insérez ce qui suit dans votre ~/.bashrc:

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

Ensuite, vous pouvez librement appeler votre commande à partir de vos scripts.


Cela fonctionne presque ... le seul problème est que je dois pouvoir passer différents drapeaux à l'exécutable "mpiexec" ... Par exemple, je dois pouvoir exécuter quelque chose comme "petsc -n 40 myexecutable" avec le alias "petsc"
Paul

4
@Paul: J'ai ajouté "$@"juste pour gérer les arguments.
enzotib

12

Les fonctions shell et les alias sont limités au shell et ne fonctionnent pas dans les scripts shell exécutés. Alternatives pour votre cas:

  • (si vous ne prenez pas la peine d'utiliser mpiexecau lieu de petsc) Ajoutez $HOME/petsc-3.2-p6/petsc-arch/binà votre PATHvariable. Cela peut être fait en éditant ~/.profileet en ajoutant:

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

    Se reconnecter pour appliquer ces changements

  • Créer le répertoire ~/binet

    • faire un script wrapper nommé petsccontenant:

      #!/bin/sh
      exec ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    • si le programme le permet, vous pouvez ignorer le shellscript et créer un lien symbolique à l'aide de la commande suivante:

      ln -s ~/petsc-3.2-p6/petsc-arch/bin/mpiexec ~/bin/petsc

9

En bash 4 , vous pouvez utiliser la variable spéciale: $BASH_ALIASES.

Par exemple:

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

Sinon, définissez comme variable, puis utilisez la substitution de commande ou eval.

Ainsi, par exemple, au lieu de définir un alias tel que:

alias foo="echo test"

le définir comme:

foo="echo test"

au lieu. Puis exécutez-le soit:

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

ou:

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

Bien que les alias soient déconseillés au profit des fonctions du shell, cette réponse est la seule qui devrait être acceptée. Même l’ancienne Debian 8 a la version 4 de bash, c’est donc ${BASH_ALIASES[alias]}une bonne option. Sinon, je devais éditer beaucoup de lignes de mes .bash_aliases pour appliquer d'autres choses. Je vous remercie.
erm3nda

8

Vous pouvez forcer bash à exécuter votre script en tant que shell interactif avec l'indicateur -i. Cela indiquera à votre fichier .bashrc de définir des alias et d’autres fonctions.

Exemple:

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

Plus d'informations:

$ man bash

2
.bashrcest également lu lors de l'exécution d'une commande SSH non interactive (c'est pourquoi il dispose d'un contrôle d'interactivité en haut)
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).

Donc, la vraie réponse à cette question, pour ceux qui cherchent à utiliser des alias réels dans des scripts de shell au lieu de leurs alternatives, est la suivante:

#!/bin/bash

shopt -s expand_aliases

alias foo=bar

foo whatever

Quant à la raison pour laquelle je veux faire ceci: En raison de circonstances inhabituelles, je dois duper une Dockerfile en pensant qu'il est un script shell.


4
  1. Dans .bash_aliases:

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

    Ou mettez la fonction dans .bashrc. Habituellement, .bashrcseuls les paramètres de configuration de bashsont enregistrés.

  2. Dans le terminal: source .bash_aliases

  3. Appeler: petsc arg(s)

Avantage: vous n'avez pas besoin export -f petscdans .bash_aliases. Les alias sont déconseillés, mais l'utilisation .bash_aliasesde fonctions est correcte.


J'aime cette solution, je l'essayerai plus tard
Greenonline le

2
  1. Utilisez vos alias dans votre script shell.
  2. Source votre script dans votre shell interactif actuel au lieu de l'exécuter.

Donc, si vous avez un fichier appelé script.shavec vos commandes incluant l’utilisation d’alias, tapez simplement:

source script.sh

@ DavidFoerster Cette méthode fonctionne bien. Le fait de rechercher un script à l'aide de .ou sourcebuiiltin force le shell actuel à exécuter toutes les commandes qu'il contient . Si le développement d'alias se produit dans le shell dans lequel .ou sourceest exécuté, il se produit. Cependant, il est important de réaliser que cette méthode n’est parfois utile, car on a souvent besoin ou on veut exécuter un script dans son propre shell, avec son propre environnement. Les scripts shell écrits dans l'intention d'être exécutés de la manière habituelle ne doivent généralement pas être recherchés, ils ne fonctionneront souvent pas correctement.
Eliah Kagan

@EliahKagan: Merci. Maintenant, je comprends ce que la réponse est censée vouloir dire. Je vais ajouter une explication.
David Foerster

1

(EDIT: fonctions supprimées car j'ai mal interprété l'appel de mpiexec.)

Si la seule chose dont vous avez besoin est de moins taper, pourquoi ne pas simplement placer le dossier dans $ PATH? Ou créer un lien symbolique vers mpiexec depuis un dossier de $ PATH? Ou (mon préféré) mettre l'alias dans un script que vous source dans le script d'appel?


1
La raison pour laquelle je ne peux pas le mettre dans mon $ PATH est parce que j'ai un autre fichier 'mpiexec' dans un autre répertoire qui est déjà dans mon $ PATH. Si j'ajoute le chemin d'accès à ce nouveau "mpiexec", il tentera probablement de les exécuter tous les deux ... n'est-ce pas?
Paul

1
Je ne comprends pas pourquoi ne pas simplement utiliser "$@".
enzotib

2
Paul, il va essayer d'exécuter celui qui est le premier dans PATH, pas les deux.
Unhammer

enzotib, ah, j’ai mal interprété le nom de mpiexec, j’ai pensé que tous les arguments devaient être réunis. Will modifier ma réponse :)
unhammer
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.