Dlaczego mój skrypt Bash nie rozpoznaje aliasów?

216

W moim ~/.bashrcpliku znajdują się dwie definicje:

  1. commandA, który jest aliasem na dłuższą ścieżkę
  2. commandB, który jest aliasem skryptu Bash

Chcę przetworzyć ten sam plik za pomocą tych dwóch poleceń, więc napisałem następujący skrypt Bash:


#!/bin/bash

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

Nawet po wylogowaniu się z sesji i ponownym zalogowaniu się, Bash monituje mnie o command not foundbłędy dla obu poleceń podczas uruchamiania tego skryptu.

Co ja robię źle?

Zaid
źródło
10
BTW, nie trzeba się logować i wylogowywać, aby rozpoznać alias. Musisz tylko zrobić source ~/.bashrc.
tshepang
W moim przypadku zostałem połączony przez agenta SSH zdalnie, po dodaniu aliasu, gdy zamknąłem agenta SSH i połączyłem ponownie, zaczął działać.
dav
Alias ​​to sposób na skrócenie polecenia. (Są używane tylko w interaktywnych powłokach, a nie w skryptach - to jedna z niewielu różnic między skryptem a interaktywną powłoką.)
Kris Roofe

Odpowiedzi:

117

Po pierwsze, jak powiedział ddeimeke, aliasy domyślnie nie są rozszerzane w nieinteraktywnych powłokach.

Po drugie, .bashrcnie jest odczytywany przez nieinteraktywne powłoki, chyba że ustawisz BASH_ENVzmienną środowiskową.

Ale co najważniejsze: nie rób tego! Proszę? Pewnego dnia przeniesiesz ten skrypt w miejsce, w którym nie zostaną ustawione niezbędne aliasy, i ponownie się zepsuje.

Zamiast tego ustaw i używaj zmiennych środowiskowych jako skrótów w skrypcie:

#!/bin/bash

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

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

źródło
5
To rozwiązanie nie działa w zwykłych aliasprzypadkach użycia. Np alias mv="mv -v --backup=numbered".
Evi1M4chine 23.04.16
@ Evi1M4chine: Tak, robi. Przynajmniej po przywróceniu Gillesowi niepotrzebnej edycji. Ale i tak może być lepiej użyć innej zmiennej dla parametrów.
1
Ach, zwróć uwagę na brak cudzysłowów wokół $CMDA/ $CMDB… Poza zmiennymi pisanymi dużymi literami dla samego basha w bashu i naprawdę działa, ten brak cytatów sprawia, że ​​jestem naprawdę niespokojny… W każdym razie dzięki.
Evi1M4chine 30.04.16
@ Evi1M4chine: Uh, co? 1. Sam usunąłem cytaty w najnowszej edycji. 2. skąd bierzesz „zastrzeżone dla samego basha”? to byłby pierwszy, jaki o tym słyszałem. 3. Jeśli to sprawia , że czujesz się nieswojo, co myślisz o używaniu basha? W każdym razie użyj oddzielnej zmiennej dla opcji, jak ci mówiłem.
1
@alvas: założono, że gizmonie ma ścieżki lub istnieje polecenie o tej samej nazwie, ale o wyższym priorytecie. w przeciwnym razie możesz po prostu ustawić CMDAzwykły na zwykły gizmo.
161

Jeśli zajrzysz na stronę bash, znajdziesz:

Aliasy nie są rozwijane, gdy powłoka nie jest interaktywna, chyba że ustawiono opcję powłoki expand_aliases za pomocą shopt (patrz opis shopt w POLECENIA WBUDOWANE POWŁOKI poniżej).

Więc umieść

shopt -s expand_aliases

w twoim skrypcie.

Po ustawieniu tego w skrypcie należy źródłowy plik aliasów.

shopt -s expand_aliases
source ~/.bash_aliases
ddeimeke
źródło
7
Umieściłem go w skrypcie, ale nadal nie działa. Ten sam błąd.
Zaid
5
Dodawanie shopt -s expand_aliases source ~/.bash_aliasesdziała dla mnie idealnie. Często w .bashrc istnieje forma interaktywnego wykrywania powłoki: # If not running interactively, don't do anything [ -z "$PS1" ] && return@Zaid, Może chcesz to sprawdzić w pliku, który pozyskałeś.
Frank Schubert,
1
doskonały! zapisałem moje skrypty !! :) tak trudno jest czytać / wyszukiwać / przeglądać informacje i strony w terminalu, że dawno temu zrezygnowałem i szukałem w Internecie ...
Aquarius Power
2
Co ciekawe, shopt -s expand_aliasesnie trzeba iść przed definicją aliasu, ale przed użyciem aliasu. Dodawanie do @FrankSchubert: Interaktywne wykrywanie powłoki może być również wykonane przy użyciu $-opcji, które zawierają opcje powłoki, szczególnie ijeśli powłoka jest interaktywna.
ważne
2
to nie jest poprawna odpowiedź ... Pozyskiwanie aliasów w skrypcie nie jest odpowiedzią. Twój ~/.bash_aliasesmoże zależeć od innych rzeczy poprzednio załadowanego na interaktywnej powłoki ... Najbliższy rzeczą znalazłem zmienia swój hashbang do #!/bin/bash -liWciąż nie jest doskonały. Idealnie powinieneś używać funkcji, a nie aliasów.
Stefanos Kalantzis
44

Aliasów nie można eksportować, więc nie są dostępne w skryptach powłoki, w których nie są zdefiniowane. Innymi słowy, jeśli je zdefiniujesz, ~/.bashrcnie będą dostępne your_script.sh(chyba, że ​​podasz ~/.bashrcw skrypcie, czego nie poleciłbym, ale istnieją sposoby, aby to zrobić poprawnie).

Funkcje można jednak wyeksportować i byłyby dostępne dla skryptów powłoki uruchamianych ze środowiska, w którym są zdefiniowane. Można to zrobić umieszczając to w swoim bashrc:

bla()
{
    echo „Witaj świecie!”
}
eksport -f foo

Jak napisano w podręczniku Bash: „W prawie każdym celu funkcje powłoki są lepsze niż aliasy”.

Dennis Williamson
źródło
1
Chociaż technicznie to nie odpowiada na pytanie, jak mówisz, możesz po prostu zastąpić alias commandA=...go commandA() { ... }wtedy export commandAi otrzymasz identyczne zachowanie jak alias. Jest to prawie identyczna alternatywa dla aliasów, o ile wiem, która działa świetnie w skryptach bash
Phylliida
Problem polega na tym, że potrzebujesz aliasu, do którego przekazujesz wiele cytowanych opcji. na przykład alias b=bashułatwia wykonywanie czynności, b -c "echo test | grep test"które byłyby trudne w funkcjach.
Fmstrat
@Fmstrat: b () { bash "$@"; }następnieb -c "echo test | grep test"
Dennis Williamson
11
[cmd line] > bash -i [your script's file path]

To ijest dla interaktywnych i źródła twój bashprofil dla ciebie.

użytkownik65576
źródło
-5

Odkryłem, że czasami skrypt bash również nie rozpoznaje eksportu. Jednak zmieniając go na

#!/bin/sh

pracuje dla mnie.

lwpro2
źródło
1
Nie, nie ...
Hafiz Temuri,