Ejecutar un ejecutable en RUTA con el mismo nombre que una función existente

16

A veces defino una función que sombrea un ejecutable y modifica sus argumentos o resultados. Entonces, la función tiene el mismo nombre que el ejecutable, y necesito una forma de ejecutar el ejecutable desde la función sin llamarla recursivamente. Por ejemplo, para ejecutar automáticamente la salida de fossil diffthrough colordiffy less -Ruso:

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 estuviera seguro de la ubicación del ejecutable, simplemente podría escribir /usr/bin/fossil. Bash reconoce que eso /significa que el comando es un ejecutable, no una función. Pero como no conozco la ubicación exacta, tengo que recurrir a llamar whichy verificar el resultado. ¿Hay una manera más sencilla?

Petr Pudlák
fuente
1
Usted dice: "Bash reconoce que eso /significa que el comando es un ejecutable, no una función". Estrictamente hablando, eso no es cierto. En lo que creo que es una decisión de diseño horrible (e indocumentada), bash permite que los nombres de funciones contengan barras diagonales. Las barras simplemente hacen /usr/bin/fossilque sea una cadena diferente de fossil, por lo que, cuando dices /usr/bin/fossil, no intenta ejecutar la fossilfunción.
G-Man dice 'reinstalar a Monica' el

Respuestas:

19

Use el commandcaparazón incorporado:

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.
hombre trabajando
fuente
2
Una opción más es escapar del comando \date.
jordanm
44
@jordanm, eso solo funciona para los alias. La pregunta era sobre funciones. pastebin.com/TgkHQwbb
manatwork
3

En los scripts, la #!línea a menudo se usa /bin/env bashpara ejecutar el comando bash en función de la ruta. (Puede diferir para algunas utilidades). Esto debería funcionar aquí también ...

(La commandalternativa también debería funcionar, pero podría depender de un shell específico) (Funciona en Bourne Shell en Solaris, pero en realidad se ejecuta /bin/commanden ese caso, que es un shell incorporado en Bash)

Ambos /bin/commandy /bin/envse enumeran en SUS, por lo que todas las implementaciones compatibles deberían tenerlo.

Gert van den Berg
fuente
Gracias por señalar env. Tenía dudas sobre qué respuesta debería aceptar, pero como la pregunta es sobre bash , su commandsolución integrada es la mejor.
Petr Pudlák
1
En mi Linux no hay commandejecutable, pero commandtambién funciona en dash, kshy zsh. Así que supongo que es un caparazón incorporado no solo en bash. pastebin.com/fi3gyNse
manatwork
No es un buildin en Solaris 10 Bourne (que también está disponible como heirloom-sh). Las ventajas de un ejecutable con una ruta conocida es que una función no puede sobrescribirlo.
Gert van den Berg
(La ausencia de / bin / command podría explicar por qué los scripts se usan /bin/envdespués del hash-bang si no quieren codificar la ruta del shell)
Gert van den Berg
3

La respuesta de Gert me hizo darme cuenta de que también se puede usar nicecon el propósito (en realidad lo tuve en uno de mis scripts sin darme cuenta):

$ 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

Es menos elegante que las otras respuestas, pero en algunas circunstancias podría ser una opción útil.

Petr Pudlák
fuente
Es posible que desee ampliar este para incluir una alternativa similar: `which date`.
Eliah Kagan
1
@EliahKagan El problema `which something`es que si no hay un somethingejecutable, pueden pasar cosas desafortunadas. Por ejemplo, si echofalta, entonces `which echo` /bin/rm preciousFilehace algo muy diferente de lo previsto.
Petr Pudlák