Wie führe ich einen Alias ​​in einem Shell-Skript aus?

101

Ich habe eine ausführbare Datei mpiexec, deren vollständiger Pfad ist ~/petsc-3.2-p6/petsc-arch/bin/mpiexec. Da ich diesen Befehl in verschiedenen Verzeichnissen ausführen möchte (ohne den gesamten Pfad erneut eingeben zu müssen), richte ich in meiner Ausgangsdatei einen Alias ​​ein .bashrc:

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

Dadurch kann ich diese mpiexecDatei einfach an der Eingabeaufforderung ausführen, indem ich Folgendes eingebe:

petsc myexecutable

Ich habe versucht, eine Shell-Skriptdatei mit dem Namen zu schreiben script, wobei mein neuer Alias petscals Befehl verwendet wurde. Nachdem ich meinem Shell-Skript die entsprechenden Berechtigungen erteilt hatte (mithilfe von chmod), versuchte ich, das Skript auszuführen. Es gab mir jedoch den folgenden Fehler:

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

Ich weiß, dass ich einfach den vollständigen Pfad zur mpiexecDatei schreiben könnte , aber es ist umständlich, den vollständigen Pfad jedes Mal zu schreiben, wenn ich ein neues Skript schreiben möchte. Kann ich meinen Alias petscin der Skriptdatei verwenden? Gibt es eine Möglichkeit, meine zu bearbeiten .bashrcoder .bash_profileum dies zu ermöglichen?

Paul
quelle
Wie wäre es, den Alias ​​hinzuzufügen .bash_aliases? Wie wäre es auch mit einem Aliasing des absoluten Pfades anstelle eines relativen Pfades wiealias petsc='/home/user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
Nitin Venkatesh
@nitstorm: Keine der beiden Lösungen scheint zu funktionieren ... Ich erhalte immer noch den gleichen Fehler wie zuvor
Paul
Related: unix.stackexchange.com/questions/1496/…
AlikElzin-kilaka

Antworten:

74
  1. Verwenden Sie in Ihrem Shell-Skript den vollständigen Pfad und nicht einen Alias.

  2. Legen Sie in Ihrem Shell-Skript eine Variable und eine andere Syntax fest

    petsc='/home/your_user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
    
    $petsc myexecutable
  3. Verwenden Sie eine Funktion in Ihrem Skript. Wahrscheinlich besser, wenn petsces komplex ist

    function petsc () {
        command 1
        command 2
    }
    
    petsc myexecutable
  4. Beschaffe deine Aliase

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

Sie wollen wahrscheinlich nicht Ihre Quelle .bashrc, also, IMO, wäre eine der ersten 3 besser.

Panther
quelle
16
Punkt 4 funktioniert nicht, es sei denn, Sie verwenden shopt -s expand_aliasesdasselbe Skript.
Enzotib
Ihr Vorschlag 2) funktioniert, aber ich möchte den gleichen Befehl in mehreren Shell-Skripten verwenden können, ohne die erste Zeile petsc = "..." schreiben zu müssen. Gibt es eine Möglichkeit, dies zu tun?
Paul
1
@enzotib - danke, das habe ich zu meiner Antwort hinzugefügt.
Panther
1
In Punkt 2 setzen Sie keinen Alias, sondern eine Variable.
Pabouk
1
Nicht von OP angefragt, aber relevant für den Fragentitel: Punkt 2 funktioniert nicht mit Befehlen, die enthalten |. Verwenden Sie hier shopt -s expand_aliases& local alias, z. B. alias myalias='echo abc|rev'- erfordert vor der Verwendung einen Zeilenumbruch (siehe ALIASES in man bash). Punkt 4: Ausgelagerte Datei kann die nicht interaktive Ausführung, dh in einem Skript, verhindern. Suchen Sie nach früh exitoder return, zum Beispiel [ -z "$PS1" ] && return( überprüft , ob primäre Eingabeaufforderung nicht gesetzt anzeigt , nicht-interaktiv Shell) oder es kann eine Prüfung für seine iin $-( $-enthält Shell - Optionen, ibedeutet interaktiv). Siehe man bashfür diese Variablen.
Gültig ab dem
61

Aliase werden zugunsten von Shell-Funktionen abgelehnt. Von der bashManualseite:

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

Um eine Funktion zu erstellen und in Unterschalen zu exportieren, fügen Sie Folgendes in Ihre ~/.bashrc:

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

Dann können Sie Ihren Befehl von Ihren Skripten aus frei aufrufen.

Enzotib
quelle
Das funktioniert fast ... das einzige Problem ist, dass ich in der Lage sein muss, verschiedene Flags an die ausführbare Datei "mpiexec" zu übergeben ... Zum Beispiel muss ich etwas wie "petsc -n 40 myexecutable" mit dem ausführen können alias "petsc"
Paul
4
@Paul: Ich habe "$@"nur hinzugefügt , um mit Argumenten umzugehen .
Enzotib
12

Shell-Funktionen und Aliase sind auf die Shell beschränkt und funktionieren nicht in ausgeführten Shell-Skripten. Alternativen für Ihren Fall:

  • (wenn Sie sich nicht die Mühe machen, mpiexecstatt zu verwenden petsc) Fügen Sie $HOME/petsc-3.2-p6/petsc-arch/binIhrer PATHVariablen hinzu. Dies kann durch Bearbeiten ~/.profileund Anhängen erfolgen:

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

    Melden Sie sich erneut an, um diese Änderungen zu übernehmen

  • Erstellen Sie das Verzeichnis ~/binund

    • Erstelle ein Wrapper-Skript mit dem Namen petsc:

      #!/bin/sh
      exec ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    • Wenn das Programm dies zulässt, können Sie das Shellscript überspringen und mit dem folgenden Befehl einen Symlink erstellen:

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

In bash 4 können Sie spezielle Variable verwenden: $BASH_ALIASES.

Zum Beispiel:

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

Alternativ können Sie als Variable definieren und dann die Befehlssubstitution oder verwenden eval.

Anstatt den Alias ​​wie folgt zu definieren:

alias foo="echo test"

definiere es als:

foo="echo test"

stattdessen. Führen Sie es dann aus, indem Sie entweder:

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

oder:

find . -type f -exec sh -c "echo `$foo`" \;
Kenorb
quelle
Obwohl Aliase zugunsten von Shell-Funktionen abgelehnt werden, ist diese Antwort die einzige, die akzeptiert werden sollte. Sogar das alte Debian 8 hat Version 4 von Bash, also ${BASH_ALIASES[alias]}ist das eine nette Option. Ansonsten musste ich viele Zeilen meiner .bash_aliases bearbeiten, um andere Dinge anzuwenden. Danke.
erm3nda
8

Sie können Bash zwingen, Ihr Skript als interaktive Shell mit dem Flag -i auszuführen. Dadurch wird Ihre .bashrc-Datei angewiesen , Aliase und andere Funktionen zu definieren.

Beispiel:

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

Mehr Info:

$ man bash
Amado Martinez
quelle
2
.bashrcwird auch während der nicht interaktiven Ausführung von SSH-
Befehlen
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).

Die eigentliche Antwort auf diese Frage für diejenigen, die tatsächliche Aliase in Shell-Skripten anstelle von Alternativen zu diesen verwenden möchten, lautet:

#!/bin/bash

shopt -s expand_aliases

alias foo=bar

foo whatever

Was den Grund betrifft, warum ich das tun möchte: Aufgrund ungewöhnlicher Umstände muss ich ein Dockerfile täuschen, dass es sich um ein Shell-Skript handelt.

Konto wegwerfen
quelle
4
  1. In .bash_aliases:

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

    Oder setzen Sie die Funktion in .bashrc. Normalerweise werden in .bashrcconfig nur Einstellungen von bashgespeichert.

  2. Im Terminal: source .bash_aliases

  3. Nennen: petsc arg(s)

Vorteil: Sie brauchen nicht export -f petscin .bash_aliases. Aliase sind veraltet, aber die Verwendung .bash_aliasesfür Funktionen ist in Ordnung.

Timo
quelle
Ich mag diese Lösung, ich werde es später versuchen
Greenonline
2
  1. Verwenden Sie Ihre Aliase in Ihrem Shell-Skript.
  2. Geben Sie Ihr Skript in Ihre aktuelle interaktive Shell ein, anstatt es auszuführen.

Wenn Sie also eine Datei script.shmit Ihren Befehlen haben, die die Verwendung von Aliasen enthalten, geben Sie einfach Folgendes ein:

source script.sh
Gordon Erlebacher
quelle
@DavidFoerster Diese Methode funktioniert gut. Wenn Sie ein Skript mit dem Befehl .oder dem sourceBefehl erstellen, führt die aktuelle Shell alle darin enthaltenen Befehle aus. Wenn eine Aliaserweiterung in der Shell erfolgen würde, in der .oder ausgeführt sourcewird, tritt sie auf. Es ist jedoch wichtig zu wissen, dass diese Methode nur manchmal nützlich ist, da häufig ein Skript in einer eigenen Shell mit eigener Umgebung ausgeführt werden muss oder möchte. Shell-Skripte, die in der Absicht geschrieben wurden, auf die übliche Weise ausgeführt zu werden, sollten normalerweise nicht als Quelle verwendet werden - sie funktionieren oft nicht richtig.
Eliah Kagan
@ EliahKagan: Danke. Jetzt verstehe ich, was die Antwort bedeuten soll. Ich werde eine Erklärung hinzufügen.
David Foerster
1

(BEARBEITEN: Funktionen entfernt, da ich den Aufruf von mpiexec falsch gelesen habe.)

Wenn Sie nur weniger tippen müssen, warum legen Sie den Ordner nicht einfach in $ PATH ab? Oder aus einem Ordner in $ PATH einen Symlink zu mpiexec erstellen? Oder (mein Favorit) den Alias ​​in ein Skript einfügen, das Sie im aufrufenden Skript erstellt haben?

unhammer
quelle
1
Der Grund, warum ich es nicht in meinen $ PATH schreiben kann, ist, dass ich eine andere 'mpiexec'-Datei in einem anderen Verzeichnis habe, das sich bereits in meinem $ PATH befindet. Wenn ich den Pfad zu diesem neuen 'mpiexec' hinzufüge, wird es wahrscheinlich versuchen, beide auszuführen ... nicht wahr?
Paul
1
Kann nicht verstehen, warum nicht einfach verwenden "$@".
Enzotib
2
Paul, es wird versucht, den ersten im PATH auszuführen, nicht beide.
Unhammer
enzotib, ah, ich habe die Art und Weise, wie mpiexec aufgerufen wurde, falsch verstanden. Wird meine Antwort bearbeiten :)
Unhammer