Uruchamianie pliku wykonywalnego w PATH o takiej samej nazwie jak istniejąca funkcja

16

Czasami definiuję funkcję, która cienia plik wykonywalny i poprawia jego argumenty lub dane wyjściowe. Więc funkcja ma taką samą nazwę jak plik wykonywalny i potrzebuję sposobu, w jaki sposób uruchomić plik wykonywalny z funkcji bez wywoływania funkcji rekurencyjnie. Na przykład, aby automatycznie uruchomić wyjście fossil diffprzez colordiffi less -Rużywam:

function fossil () {
    local EX=$(which fossil)
    if [ -z "$EX" ] ; then
        echo "Unable to find 'fossil' executable." >&2
        return 1
    fi
    if [ -t 1 ] && [ "$1" == "diff" ] ; then
        "$EX" "$@" | colordiff | less -R
        return
    fi
    "$EX" "$@"
}

Gdybym był pewien lokalizacji pliku wykonywalnego, mógłbym po prostu wpisać /usr/bin/fossil. Bash rozpoznaje, że /oznacza to, że jest to plik wykonywalny, a nie funkcja. Ale ponieważ nie znam dokładnej lokalizacji, muszę zadzwonić whichi sprawdzić wynik. Czy istnieje prostszy sposób?

Petr Pudlák
źródło
1
Mówisz: „Bash rozpoznaje, że /oznacza to, że polecenie jest wykonywalne, a nie funkcją”. Ściśle mówiąc, to nie prawda. W moim przekonaniu, że jest to okropna (i nieudokumentowana) decyzja projektowa, bash pozwala, aby nazwy funkcji zawierały ukośniki. W ukośniki po prostu spowodować /usr/bin/fossil, aby być inna struna od fossiltak, kiedy mówisz /usr/bin/fossil, że nie próbuje uruchomić fossilfunkcję.
G-Man mówi „Reinstate Monica”

Odpowiedzi:

19

Użyj commandwbudowanej powłoki:

bash-4.2$ function date() { echo 'at the end of days...'; }

bash-4.2$ date
at the end of days...

bash-4.2$ command date
Mon Jan 21 16:24:33 EET 2013

bash-4.2$ help command
command: command [-pVv] command [arg ...]
    Execute a simple command or display information about commands.

    Runs COMMAND with ARGS suppressing  shell function lookup, or display
    information about the specified COMMANDs.  Can be used to invoke commands
    on disk when a function with the same name exists.
człowiek w pracy
źródło
2
Jeszcze jedną opcją jest ucieczka z polecenia \date.
Jordan
4
@jordanm, który działa tylko w przypadku aliasów. Pytanie dotyczyło funkcji. pastebin.com/TgkHQwbb
manatwork
3

W skryptach #!linia często służy /bin/env bashdo uruchamiania polecenia bash na podstawie ścieżki. (Może się różnić w przypadku niektórych narzędzi). To też powinno tu działać ...

( commandAlternatywa powinna również działać, ale może zależeć od konkretnej powłoki) (Działa na powłoce Bourne'a w systemie Solaris, ale w rzeczywistości działa/bin/command w tym przypadku, która jest powłoką wbudowaną w Bash)

Zarówno /bin/commandi /bin/envjest wymieniony w SUS, więc wszystkie implementacje zgodne powinien ją mieć.

Gert van den Berg
źródło
Dzięki za wskazanie env. Miałem wątpliwości, którą odpowiedź powinienem zaakceptować, ale ponieważ pytanie dotyczy bash , jego wbudowane commandrozwiązanie jest najlepszym rozwiązaniem.
Petr Pudlák
1
W moim systemie Linux nie ma commandpliku wykonywalnego, ale commanddziała także w dash, kshi zsh. Zakładam więc, że jest to powłoka wbudowana nie tylko w bash. pastebin.com/fi3gyNse
manatwork
To nie jest dodatek do Solaris 10 Bourne (dostępny również jako heirloom-sh). Zalety pliku wykonywalnego ze znaną ścieżką polega na tym, że nie można go zastąpić funkcją.
Gert van den Berg
(Brak komendy / bin / może wyjaśnić, dlaczego skrypty używają /bin/envpo haszowaniu, jeśli nie chcą sztywno kodować ścieżki powłoki)
Gert van den Berg
3

Odpowiedź Gerta uświadomiła mi, że można również użyć nicedo tego celu (faktycznie miałem go w jednym ze swoich skryptów, nie zdając sobie z tego sprawy):

$ function date() { echo 'at the end of days...'; }
$ date
at the end of days...
$ nice -n0 date
Mon Jan 21 16:45:21 CET 2013

Jest mniej elegancki niż inne odpowiedzi, ale w niektórych okolicznościach może być przydatną opcją.

Petr Pudlák
źródło
Może chcesz rozszerzyć tak, aby zawierały podobną alternatywą: `which date`.
Eliah Kagan
1
@EliahKagan Problem `which something`polega na tym, że jeśli nie ma somethingpliku wykonywalnego, mogą się zdarzyć niefortunne rzeczy. Na przykład, jeśli echobrakuje, to `which echo` /bin/rm preciousFilerobi coś zupełnie innego niż zamierzone.
Petr Pudlák