Jak uruchomić alias w skrypcie powłoki?

101

Mam plik wykonywalny mpiexec, którego pełna ścieżka to ~/petsc-3.2-p6/petsc-arch/bin/mpiexec. Ponieważ chcę wykonać to polecenie w różnych katalogach (bez konieczności ponownego wpisywania całej ścieżki), ustawiam alias w moim .bashrcpliku domowym :

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

co pozwala mi mpiexecłatwo wykonać ten plik w wierszu polecenia, wpisując:

petsc myexecutable

Próbowałem napisać plik skryptu powłoki o nazwie script, używając mojego nowego aliasu petscjako polecenia. Po udzieleniu skryptowi powłoki odpowiednich uprawnień (za pomocą chmod) próbowałem uruchomić skrypt. Dał mi jednak następujący błąd:

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

Wiem, że mogłem napisać pełną ścieżkę do mpiexecpliku, ale kłopotliwe jest zapisywanie pełnej ścieżki za każdym razem, gdy chcę napisać nowy skrypt. Czy istnieje sposób na użycie mojego aliasu petscw pliku skryptu? Czy istnieje sposób, w jaki mogę edytować moją wersję .bashrclub .bash_profilesprawić, aby tak się stało?

Paweł
źródło
Co powiesz na dodanie aliasu .bash_aliases? A może aliasing ścieżki bezwzględnej zamiast ścieżki względnejalias petsc='/home/user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
Nitin Venkatesh
@nitstorm: Żadne z tych rozwiązań nie działa ... Nadal pojawia się taki sam błąd jak poprzednio
Paul
Powiązane: unix.stackexchange.com/questions/1496/…
AlikElzin-kilaka

Odpowiedzi:

74
  1. W skrypcie powłoki użyj pełnej ścieżki zamiast aliasu.

  2. W skrypcie powłoki ustaw zmienną, inną składnię

    petsc='/home/your_user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
    
    $petsc myexecutable
  3. Użyj funkcji w skrypcie. Prawdopodobnie lepiej, jeśli petscjest złożony

    function petsc () {
        command 1
        command 2
    }
    
    petsc myexecutable
  4. Źródło aliasów

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

Prawdopodobnie nie chcesz źródła .bashrc, więc, IMO, jedna z pierwszych 3 byłaby lepsza.

Pantera
źródło
16
Punkt 4 nie działa, chyba że użyjesz shopt -s expand_aliasestego samego skryptu.
enzotib
Twoja sugestia 2) działa, ale chcę móc używać tego samego polecenia w wielu skryptach powłoki bez konieczności pisania pierwszego wiersza petsc = "...". Czy jest na to sposób?
Paul
1
@enzotib - dziękuję, dodałem to do mojej odpowiedzi.
Panther
1
W punkcie 2 nie ustawiasz aliasu, ale zmienną.
pabouk
1
OP nie jest wymagane, ale dotyczy tytułu pytania: Punkt 2 nie będzie działał z poleceniami zawierającymi |. Tutaj użyj shopt -s expand_aliases& lokalnego aliasu, np. alias myalias='echo abc|rev'- wymaga podziału linii przed użyciem (patrz ALIASY w man bash). Punkt 4: Plik źródłowy może uniemożliwić nieinteraktywne wykonanie, tj. W skrypcie. Spójrz na początku exitlub returnna przykład [ -z "$PS1" ] && return(sprawdza, czy podstawowym szybka nie jest ustawiony wskazując nieinteraktywną shell) lub może być czek na iw $-( $-zawiera opcje powłoki, ioznacza interaktywny). Zobacz man bashte zmienne.
ważne
61

Aliasy są przestarzałe na rzecz funkcji powłoki. Ze strony bashpodręcznika:

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

Aby utworzyć funkcję i wyeksportować ją do podpowłoki, umieść w swoim ~/.bashrc:

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

Następnie możesz swobodnie wywoływać polecenia ze skryptów.

enzotib
źródło
To prawie działa ... jedynym problemem jest to, że muszę móc przekazywać różne flagi do wykonywalnego „mpiexec” ... Na przykład muszę być w stanie wykonać coś takiego jak „Petsc -n 40 myexecutable” za pomocą alias „petsc”
Paul
4
@Paul: Dodałem "$@"tylko do obsługi argumentów.
enzotib
12

Funkcje i aliasy powłoki są ograniczone do powłoki i nie działają w wykonywanych skryptach powłoki. Alternatywy dla twojego przypadku:

  • (jeśli nie masz zamiaru używać mpiexeczamiast petsc) Dodaj $HOME/petsc-3.2-p6/petsc-arch/bindo swojej PATHzmiennej. Można to zrobić, edytując ~/.profilei dołączając:

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

    Zaloguj się ponownie, aby zastosować te zmiany

  • Utwórz katalog ~/bini

    • stwórz skrypt otoki petsczawierający:

      #!/bin/sh
      exec ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    • jeśli program na to pozwala, możesz pominąć skrypt powłoki i utworzyć dowiązanie symboliczne za pomocą polecenia:

      ln -s ~/petsc-3.2-p6/petsc-arch/bin/mpiexec ~/bin/petsc
Lekensteyn
źródło
9

W bash 4 można użyć zmiennej specjalnej: $BASH_ALIASES.

Na przykład:

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

Alternatywnie zdefiniuj jako zmienną, a następnie użyj podstawienia polecenia lub eval.

Na przykład zamiast definiować alias, taki jak:

alias foo="echo test"

zdefiniuj to jako:

foo="echo test"

zamiast. Następnie wykonaj to przez:

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

lub:

find . -type f -exec sh -c "echo `$foo`" \;
kenorb
źródło
Chociaż aliasy są przestarzałe na rzecz funkcji powłoki, ta odpowiedź jest jedyną, którą należy zaakceptować. Nawet stary Debian 8 ma wersję 4 bash, więc ${BASH_ALIASES[alias]}jest to fajna opcja. W przeciwnym razie musiałem edytować wiele linii moich .bash_aliases, aby zastosować inne rzeczy. Dziękuję Ci.
erm3nda
8

Możesz zmusić bash do wykonania skryptu jako interaktywnej powłoki z flagą -i. Dzięki temu plik .bashrc zdefiniuje aliasy i inne funkcje.

Przykład:

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

Więcej informacji:

$ man bash
Amado Martinez
źródło
2
.bashrcjest również odczytywany podczas wykonywania nieinteraktywnego polecenia SSH (dlatego na górze ma sprawdzanie interaktywności)
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).

Tak więc prawdziwa odpowiedź na to pytanie, dla tych, którzy chcą używać rzeczywistych aliasów w skryptach powłoki zamiast alternatyw dla nich, to:

#!/bin/bash

shopt -s expand_aliases

alias foo=bar

foo whatever

Co do tego , dlaczego chciałbym to zrobić: Z powodu niezwykłych okoliczności muszę oszukać plik Docker, aby pomyślał, że jest to skrypt powłoki.

Konto wyrzucenia
źródło
4
  1. W .bash_aliases:

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

    Lub włóż funkcję .bashrc. Zwykle są przechowywane .bashrctylko ustawienia konfiguracji bash.

  2. W terminalu: source .bash_aliases

  3. Nazwać: petsc arg(s)

Zaleta: nie trzeba export -f petscsię .bash_aliases. Aliasy są przestarzałe, ale używanie .bash_aliasesfunkcji jest w porządku.

Timo
źródło
Podoba mi się to rozwiązanie, spróbuję później
Greenonline
2
  1. Użyj swoich aliasów w skrypcie powłoki.
  2. Umieść skrypt w bieżącej, interaktywnej powłoce zamiast go uruchamiać.

Więc jeśli masz plik wywoływany za script.shpomocą poleceń, które obejmują użycie aliasów, po prostu wpisz:

source script.sh
Gordon Erlebacher
źródło
@DavidFoerster Ta metoda działa dobrze. Pozyskanie skryptu za pomocą .lub sourcebuiiltin powoduje, że bieżąca powłoka wykonuje wszystkie zawarte w nim polecenia. Jeśli rozwinięcie aliasu wystąpi w powłoce, w której uruchomiono .lub source, nastąpi ono. Jednak ważne jest, aby zdawać sobie sprawę, że ta metoda jest tylko czasami przydatna, ponieważ często trzeba lub chce wykonać skrypt we własnej powłoce, z własnym środowiskiem. Skrypty powłoki napisane z zamiarem wykonania w zwykły sposób zwykle nie powinny być pozyskiwane zamiast tego - często nie działają poprawnie.
Eliah Kagan
@EliahKagan: Dzięki. Teraz rozumiem, co ma znaczyć odpowiedź. Dodam wyjaśnienie.
David Foerster,
1

(EDYCJA: usunięto funkcje, ponieważ źle odczytałem wywołanie mpiexec.)

Jeśli jedyne czego potrzebujesz to mniej pisania, dlaczego nie umieścisz folderu w $ PATH? Lub utworzyć dowiązanie symboliczne do mpiexec z jakiegoś folderu w $ PATH? Czy (mój ulubiony) umieść alias w skrypcie, który pozyskujesz w skrypcie wywołującym?

młot
źródło
1
Powodem, dla którego nie mogę umieścić go w mojej $ PATH, jest to, że mam inny plik „mpiexec” w innym katalogu, który jest już w moim $ PATH. Jeśli dodam ścieżkę do tego nowego „mpiexec”, prawdopodobnie spróbuje wykonać oba z nich ... prawda?
Paul
1
Nie mogę zrozumieć, dlaczego po prostu nie użyć "$@".
enzotib
2
Paul, spróbuje wykonać ten, który jest pierwszy w ŚCIEŻCE, a nie oba.
młot
enzotib, ah źle odczytałem nazwę mpiexec, myślałem, że potrzebuje wszystkich argumentów jako jednego. Zmodyfikuje moją odpowiedź :)
unhammer