Warum erkennt mein Bash-Skript keine Aliase?


216

In meiner ~/.bashrcDatei befinden sich zwei Definitionen:

  1. commandADies ist ein Alias ​​für einen längeren Pfad
  2. commandBDies ist ein Alias ​​für ein Bash-Skript

Ich möchte dieselbe Datei mit diesen beiden Befehlen verarbeiten, also habe ich das folgende Bash-Skript geschrieben:


#!/bin/bash

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

Auch nach dem Abmelden von meiner Sitzung und dem erneuten Anmelden command not foundwerden bei der Ausführung dieses Skripts von Bash Fehler für beide Befehle angezeigt.

Was mache ich falsch?


10
Übrigens müssen Sie sich nicht ein- und ausloggen, um einen Alias ​​zu erkennen. Du musst es einfach tun source ~/.bashrc.
Tshepang

In meinem Fall wurde ich vom SSH-Agenten aus der Ferne verbunden, nachdem ich beim Schließen des SSH-Agenten einen Alias ​​hinzugefügt und die Verbindung wiederhergestellt hatte.
Dav

Ein Alias ​​ist eine Möglichkeit, einen Befehl zu verkürzen. (Sie werden nur in interaktiven Shells und nicht in Skripten verwendet. Dies ist einer der wenigen Unterschiede zwischen einem Skript und einer interaktiven Shell.)
Kris Roofe

Antworten:


117

Erstens, wie Ddeimeke sagte, werden Aliase standardmäßig nicht in nicht interaktiven Shells erweitert.

Zweitens .bashrcwird von nicht interaktiven Shells nur gelesen, wenn Sie die BASH_ENVUmgebungsvariable festlegen .

Aber vor allem: Tu das nicht! Bitte? Eines Tages werden Sie das Skript an einen Ort verschieben, an dem die erforderlichen Aliase nicht festgelegt sind, und es wird wieder kaputt gehen.

Setzen und verwenden Sie stattdessen Umgebungsvariablen als Verknüpfungen in Ihrem Skript:

#!/bin/bash

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

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

5
Diese Lösung funktioniert nicht für die üblichen aliasAnwendungsfälle. Eg alias mv="mv -v --backup=numbered".
Evi1M4chine

@ Evi1M4chine: Ja, das tut es. Zumindest nachdem ich Gilles überflüssig gemacht habe. Es ist jedoch möglicherweise besser, eine andere Variable für die Parameter zu verwenden.

1
Ah, beachten Sie das Fehlen von Anführungszeichen um $CMDA/ $CMDB... Abgesehen davon, dass in bash Variablen in Großbuchstaben für bash reserviert sind und es tatsächlich funktioniert, macht mich dieses Fehlen von Anführungszeichen wirklich unruhig ... Trotzdem vielen Dank.
Evi1M4chine

@ Evi1M4chine: Äh, was? 1. Ich habe die Anführungszeichen in der letzten Bearbeitung selbst entfernt. 2. Woher bekommst du das "Reserviert für Bash selbst"? Dies wäre das erste, was ich davon gehört habe. 3. Wenn das Sie unruhig macht, wie fühlen Sie sich bash in erster Linie über die Verwendung? Verwenden Sie auf jeden Fall eine separate Variable für die Optionen, wie ich Ihnen sagte.

1
@alvas: Es wird davon ausgegangen, dass gizmosich der Pfad nicht befindet oder dass es einen Befehl mit demselben Namen, aber höherer Priorität gibt. sonst könnten Sie einfachen Satz CMDAzu Ebene gizmoan erster Stelle.

161

Wenn Sie in die Bash-Manpage schauen, finden Sie:

Aliase werden nicht erweitert, wenn die Shell nicht interaktiv ist, es sei denn, die Shell-Option expand_aliases wurde mit shopt festgelegt (siehe die Beschreibung von shopt unter SHELL BUILTIN COMMANDS weiter unten).

Also leg ein

shopt -s expand_aliases

in Ihrem Skript.

Stellen Sie sicher, dass Sie Ihre Aliase-Datei als Quelle verwenden, nachdem Sie dies in Ihrem Skript festgelegt haben.

shopt -s expand_aliases
source ~/.bash_aliases

7
Ich habe es in mein Skript eingefügt, aber es funktioniert immer noch nicht. Gleicher Fehler.
Zaid

5
Das Hinzufügen shopt -s expand_aliases source ~/.bash_aliasesfunktioniert perfekt für mich. Häufig gibt es in .bashrc eine Form der interaktiven Shell-Erkennung: # If not running interactively, don't do anything [ -z "$PS1" ] && return@Zaid, Vielleicht möchten Sie dies in der von Ihnen bereitgestellten Datei überprüfen.
Frank Schubert

1
Ausgezeichnet! hat meine Skripte gespeichert !! :) Es ist so schwer, Informationen und Hilfeseiten im Terminal zu lesen / suchen / zu durchsuchen, dass ich vor langer Zeit aufgegeben habe und im Internet gesucht habe ...
Aquarius Power

2
Seltsamerweise shopt -s expand_aliasesmuss nicht vor der Alias-Definition, sondern vor der Alias-Verwendung stehen. Hinzufügen zu @FrankSchubert: Die interaktive Shell-Erkennung kann auch mithilfe von ausgeführt werden, $-die die Optionen für die Shell enthält, insbesondere iwenn die Shell interaktiv ist.
Gültig am

2
Dies ist keine korrekte Antwort. Die Suche nach Ihren Aliasnamen in Ihrem Skript ist keine Antwort. Sie ~/.bash_aliaseskönnte auf anderen Sachen hängt zuvor geladen auf einer interaktive Shell ... Das nächste , was ich gefunden wird , wenn Sie Ihre Hash - Bang auf #!/bin/bash -linoch nicht perfekt. Idealerweise sollten Sie Funktionen und keine Aliase verwenden.
Stefanos Kalantzis

44

Aliase können nicht exportiert werden, sodass sie nicht in Shell-Skripten verfügbar sind, in denen sie nicht definiert sind. Mit anderen Worten, wenn Sie sie in definieren, stehen ~/.bashrcsie nicht zur Verfügung your_script.sh(es sei denn, Sie verwenden ~/.bashrcdas Skript als Quelle , was ich nicht empfehlen würde, aber es gibt Möglichkeiten, dies ordnungsgemäß zu tun).

Funktionen können jedoch exportiert werden und stehen Shell-Skripten zur Verfügung, die in einer Umgebung ausgeführt werden, in der sie definiert sind. Dies können Sie tun, indem Sie dies in Ihren bashrc einfügen:

foo ()
{
    Echo "Hallo Welt!"
}
export -f foo

Im Bash-Handbuch heißt es: "Für fast jeden Zweck werden Shell-Funktionen den Aliasen vorgezogen."


1
Während dies technisch nicht die Frage beantworten, wie Sie sagen , Sie einfach ersetzen können alias commandA=...mit commandA() { ... }dann export commandAund Sie identisches Verhalten an den Alias erhalten. Das ist also, soweit ich weiß, eine ziemlich identische Alternative zu Aliasen, die in Bash-Skripten hervorragend funktioniert
Phylliida

Das Problem ist hier, wenn Sie einen Alias ​​benötigen, an den Sie viele der angegebenen Optionen übergeben. alias b=bashmacht es zum Beispiel einfach, b -c "echo test | grep test"was in Funktionen schwierig wäre.
Fmstrat

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

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

Das iist für interaktive und Quellen deines bashProfils für dich.


-5

Ich habe festgestellt, dass Bash-Skripte manchmal auch keinen Export erkennen. Ändern Sie es jedoch auf

#!/bin/sh

funktioniert bei mir.


1
Nein, es hat nicht ...
Hafiz Temuri
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.