Menjalankan executable di PATH dengan nama yang sama dengan fungsi yang ada

16

Kadang-kadang saya mendefinisikan fungsi yang membayangi yang dapat dieksekusi dan mengubah argumen atau outputnya. Jadi fungsinya memiliki nama yang sama dengan executable, dan saya perlu cara bagaimana menjalankan executable dari fungsi tanpa memanggil fungsi secara rekursif. Misalnya, untuk secara otomatis menjalankan output fossil diffmelalui colordiffdan less -Rsaya gunakan:

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

Jika saya yakin tentang lokasi yang dapat dieksekusi, saya cukup mengetik /usr/bin/fossil. Bash mengakui itu /berarti perintah itu dapat dieksekusi, bukan fungsi. Tetapi karena saya tidak tahu lokasi persisnya, saya harus menelepon whichdan memeriksa hasilnya. Apakah ada cara yang lebih sederhana?

Petr Pudlák
sumber
1
Anda berkata, "Bash mengakui itu /berarti perintah itu dapat dieksekusi, bukan fungsi." Sebenarnya, itu tidak benar. Dalam apa yang saya yakini sebagai keputusan desain yang mengerikan (dan tidak berdokumen), bash memungkinkan nama fungsi mengandung garis miring. Garis miring hanya menyebabkan /usr/bin/fossilmenjadi berbeda tali dari fossil, sehingga, ketika Anda mengatakan /usr/bin/fossil, tidak mencoba untuk menjalankan fossilfungsi.
G-Man Mengatakan 'Reinstate Monica'

Jawaban:

19

Gunakan commandshell builtin:

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.
manatwork
sumber
2
Satu lagi opsi adalah keluar dari perintah \date.
jordanm
4
@jordanm, itu hanya berfungsi untuk alias. Pertanyaannya adalah tentang fungsi. pastebin.com/TgkHQwbb
manatwork
3

Dalam skrip, #!baris sering digunakan /bin/env bashuntuk menjalankan perintah bash berdasarkan path. (Mungkin berbeda untuk beberapa utilitas). Ini harusnya bekerja di sini juga ...

( commandAlternatifnya juga harus bekerja, tetapi mungkin tergantung pada shell tertentu) (Ini bekerja pada Shell Bourne pada Solaris, tetapi sebenarnya berjalan /bin/commanddalam kasus itu, yang merupakan shell yang dibangun pada Bash)

Keduanya /bin/commanddan /bin/envterdaftar dalam SUS, sehingga semua implementasi yang sesuai harus memilikinya.

Gert van den Berg
sumber
Terima kasih telah menunjukkan env. Saya ragu jawaban mana yang harus saya terima, tetapi karena pertanyaannya adalah bash , bawaannyacommand adalah solusi terbaik.
Petr Pudlák
1
Di Linux saya tidak ada yang commanddapat dieksekusi, tetapi commandjuga berfungsi dash, kshdan zsh. Jadi saya menganggap itu adalah shell yang tidak hanya di dalam bash. pastebin.com/fi3gyNse
manatwork
Ini bukan buildin pada Solaris 10 Bourne (Itu juga tersedia sebagai heirloom-sh). Keuntungan dari executable dengan path yang diketahui adalah tidak bisa ditimpa oleh suatu fungsi.
Gert van den Berg
(Tidak adanya / bin / perintah mungkin menjelaskan mengapa skrip digunakan /bin/envsetelah hash-bang jika mereka tidak ingin kode-keras jalan shell)
Gert van den Berg
3

Jawaban Gert membuat saya sadar bahwa seseorang juga dapat menggunakannya niceuntuk tujuan itu (saya benar-benar memilikinya di salah satu skrip saya tanpa menyadarinya):

$ 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

Itu kurang elegan daripada jawaban lain, tetapi dalam beberapa keadaan itu bisa menjadi pilihan yang berguna.

Petr Pudlák
sumber
Anda mungkin ingin memperluas ini untuk menyertakan alternatif yang sama: `which date`.
Eliah Kagan
1
@EliahKagan Masalahnya `which something`adalah bahwa jika tidak ada yang somethingdapat dieksekusi, hal-hal yang disayangkan dapat terjadi. Misalnya jika echohilang maka `which echo` /bin/rm preciousFilelakukan sesuatu yang sangat berbeda dari yang dimaksudkan.
Petr Pudlák