Exécuter un exécutable dans PATH avec le même nom qu'une fonction existante

16

Parfois, je définis une fonction qui associe un exécutable et ajuste ses arguments ou sa sortie. Donc, la fonction a le même nom que l'exécutable, et j'ai besoin d'un moyen pour exécuter l'exécutable à partir de la fonction sans appeler la fonction de manière récursive. Par exemple, pour exécuter automatiquement la sortie de fossil diffthrough colordiffet less -Rj'utilise:

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" "$@"
}

Si j'étais sûr de l'emplacement de l'exécutable, je pourrais simplement taper /usr/bin/fossil. Bash reconnaît que cela /signifie que la commande est un exécutable, pas une fonction. Mais comme je ne connais pas l'emplacement exact, je dois recourir à l'appel whichet à la vérification du résultat. Existe-t-il un moyen plus simple?

Petr Pudlák
la source
1
Vous dites: «Bash reconnaît que cela /signifie que la commande est un exécutable, pas une fonction.» À strictement parler, ce n'est pas vrai. Dans ce que je pense être une décision de conception horrible (et non documentée), bash permet aux noms de fonctions de contenir des barres obliques. Les barres obliques provoquent simplement /usr/bin/fossilune chaîne différente de fossil, donc, quand vous dites /usr/bin/fossil, il n'essaie pas d'exécuter la fossilfonction.
G-Man dit `` Réintègre Monica '' le

Réponses:

19

Utilisez le commandshell intégré:

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.
homme au travail
la source
2
Une autre option consiste à échapper à la commande \date.
jordanm
4
@jordanm, qui ne fonctionne que pour les alias. La question portait sur les fonctions. pastebin.com/TgkHQwbb
manatwork
3

Dans les scripts, la #!ligne utilise souvent /bin/env bashpour exécuter la commande bash en fonction du chemin. (Cela peut différer pour certains utilitaires). Cela devrait également fonctionner ici ...

(L' commandalternative devrait également fonctionner, mais pourrait dépendre d'un shell spécifique) (Cela fonctionne sur le Bourne Shell sur Solaris, mais il fonctionne /bin/commanden fait dans ce cas, qui est un shell intégré à Bash)

Les deux /bin/commandet /bin/envsont répertoriés dans SUS, donc toutes les implémentations conformes devraient l'avoir.

Gert van den Berg
la source
Merci de l'avoir signalé env. J'avais des doutes quant à la réponse à donner, mais comme la question concerne bash , sa fonction intégrée commandest la meilleure solution.
Petr Pudlák
1
Sur mon Linux il n'y a pas commandexécutable, mais commandfonctionne aussi dash, kshet zsh. Je suppose donc que c'est un shell intégré non seulement dans bash. pastebin.com/fi3gyNse
manatwork
Ce n'est pas un buildin sur Solaris 10 Bourne (qui est également disponible sous le nom heirloom-sh). Les avantages d'un exécutable avec un chemin connu sont qu'il ne peut pas être écrasé par une fonction.
Gert van den Berg
(L'absence de / bin / command pourrait expliquer pourquoi les scripts utilisent /bin/envaprès le hash-bang s'ils ne veulent pas coder en dur le chemin du shell)
Gert van den Berg
3

La réponse de Gert m'a fait réaliser que l'on peut aussi l'utiliser niceà cette fin (je l'avais en fait dans l'un de mes scripts sans le savoir):

$ 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

C'est moins élégant que les autres réponses, mais dans certaines circonstances, cela pourrait être une option utile.

Petr Pudlák
la source
Vous pouvez étendre cette inclure une alternative similaire: `which date`.
Eliah Kagan
1
@EliahKagan Le problème `which something`est que s'il n'y a pas d' somethingexécutable, des choses malheureuses peuvent se produire. Par exemple, si echoest manquant, `which echo` /bin/rm preciousFilefait quelque chose de très différent de celui prévu.
Petr Pudlák