Запуск виконуваного файлу в PATH з тим самим іменем, що і існуюча функція


16

Іноді я визначаю функцію, яка затінює виконуваний файл і налаштовує його аргументи або висновки. Отже, функція має те саме ім'я, що і виконуваний файл, і мені потрібен спосіб, як запустити виконуваний файл з функції, не викликаючи функцію рекурсивно. Наприклад, для автоматичного запуску виводуfossil diff наскрізний colordiffі less -Rя використовую:

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

Якби я був впевнений у розташуванні виконуваного файлу, я міг би просто набрати /usr/bin/fossil . Bash визнає, що це /означає, що команда - це виконуваний файл, а не функція. Але оскільки я не знаю точного місця, я повинен вдатися до дзвінків whichі перевірки результату. Чи є простіший спосіб?


1
Ви говорите: "Bash розпізнає, що /означає, що команда є виконуваним, а не функцією". Строго кажучи, це неправда. Оскільки я вважаю жахливим (і незадокументованим) дизайнерським рішенням, bash дозволяє назви функцій містити косої риски. Штрихи просто призводять /usr/bin/fossilдо того, що це інший рядок від fossil, тому, коли ви говорите /usr/bin/fossil, він не намагається запустити fossilфункцію.
G-Man каже: "Відновіть Моніку"

Відповіді:


19

Використовуйте commandвбудовану оболонку:

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.

2
Ще один варіант - уникнути команди \date.
Йорданм

4
@jordanm, це працює лише для псевдонімів. Питання стосувалося функцій. pastebin.com/TgkHQwbb
manatwork

3

У сценаріях, #! рядок часто використовується /bin/env bashдля запуску команди bash на основі шляху. (Це може відрізнятися для деяких утиліт). Це має працювати і тут ...

(The command Альтернатива також повинна працювати, але може залежати від конкретної оболонки) (Вона працює на оболонці Борна на Solaris, але вона фактично працює /bin/commandв тому випадку, що це оболонка, вбудована на Bash)

І те, /bin/commandі /bin/envперелічене в SUS, тому всі сумісні реалізації повинні мати його.


Дякуємо, що вказали env. У мене були сумніви, яку відповідь слід прийняти, але оскільки питання стосується башти , його вбудований commandваріант - найкраще рішення.
Петро Пудлак

1
На моєму Linux немає commandвиконуваного файлу, але commandтакож працює в dash, kshі zsh. Тож я припускаю, що це оболонка, вбудована не тільки в bash. pastebin.com/fi3gyNse
манатурка

Це не побудова на Solaris 10 Bourne (Це також доступно як heirloom-sh). Переваги виконуваного файлу з відомим шляхом полягає в тому, що він не може бути перезаписаний функцією.
Герт ван ден Берг

(Відсутність / bin / command може пояснити, чому сценарії використовують /bin/envпісля хеш-бангу, якщо вони не хочуть жорстко кодувати шлях оболонки)
Герт ван ден Берг

3

Відповідь Герта дала мені зрозуміти, що можна використовувати і niceдля своєї мети (я насправді мав це в одному зі своїх сценаріїв, не усвідомлюючи цього):

$ 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

Він менш елегантний, ніж інші відповіді, але в деяких умовах може бути корисним варіантом.


Ви можете розширити це включити подібну альтернативу: `which date`.
Елія Каган

1
@EliahKagan Проблема `which something`полягає в тому, що якщо немає somethingвиконавчого файлу, трапляються нещасні речі. Наприклад, якщо echoцього немає, то `which echo` /bin/rm preciousFileробиться щось зовсім інше, ніж було призначено.
Петро Пудлак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.