Executando um executável no PATH com o mesmo nome de uma função existente

13

Às vezes, defino uma função que cria sombras em um executável e ajusta seus argumentos ou saída. Portanto, a função tem o mesmo nome do executável e eu preciso de uma maneira de executar o executável a partir da função sem chamar a função recursivamente. Por exemplo, para executar automaticamente a saída de fossil diff a colordiff e less -R eu uso:

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

Se eu tivesse certeza da localização do executável, eu poderia simplesmente digitar /usr/bin/fossil . O Bash reconhece que / significa que o comando é um executável, não uma função. Mas como não sei a localização exata, tenho que recorrer a chamar which e verificar o resultado. Existe uma maneira mais simples?

    
por Petr Pudlák 21.01.2013 / 15:20

3 respostas

17

Use o command shell embutido:

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.
    
por 21.01.2013 / 15:25
3

Nos scripts, a linha #! geralmente usa /bin/env bash para executar o comando bash com base no caminho. (Pode ser diferente para alguns utilitários). Isso deve funcionar aqui também ...

(A alternativa command também deve funcionar, mas pode depender de um shell específico) (Funciona no Bourne Shell no Solaris, mas na verdade executa /bin/command nesse caso, que é um shell construído no Bash)

O /bin/command e o /bin/env estão listados no SUS, portanto, todas as implementações compatíveis devem tê-lo.

    
por 21.01.2013 / 16:10
3

A resposta de Gert me fez perceber que também é possível usar nice para o propósito (na verdade eu a tive em um dos meus scripts sem perceber):

$ 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

É menos elegante do que as outras respostas, mas em algumas circunstâncias pode ser uma opção útil.

    
por 21.01.2013 / 16:46