การเรียกใช้งาน executable ใน 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 ตระหนักว่านั่น/หมายถึงคำสั่งนั้นเป็นไฟล์ปฏิบัติการไม่ใช่ฟังก์ชั่น" พูดอย่างเคร่งครัดนั่นไม่ใช่ความจริง ในสิ่งที่ฉันเชื่อว่าเป็นการตัดสินใจที่น่ากลัว (และไม่มีเอกสาร) การออกแบบทุบตีอนุญาตให้ชื่อฟังก์ชันประกอบด้วยเครื่องหมายทับ เครื่องหมายทับ/usr/bin/fossilจะทำให้สตริงแตกต่างจากfossilดังนั้นเมื่อคุณพูด/usr/bin/fossilมันจะไม่พยายามเรียกใช้fossilฟังก์ชัน
G-Man กล่าวว่า 'Reinstate Monica'

คำตอบ:


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หนึ่งในตัวเลือกมากขึ้นคือการหลบหนีคำสั่ง
jordanm

4
@jordanm ซึ่งใช้ได้กับนามแฝงเท่านั้น คำถามคือเกี่ยวกับฟังก์ชั่น pastebin.com/TgkHQwbb
จัดการ

3

ในสคริปต์#!บรรทัดมักใช้/bin/env bashเพื่อรันคำสั่ง bash ตามพา ธ (อาจแตกต่างกันไปสำหรับยูทิลิตี้บางอย่าง) นี่ควรจะทำงานที่นี่เช่นกัน ...

( commandทางเลือกควรใช้งานได้ แต่อาจขึ้นอยู่กับเชลล์ที่ระบุ) (ใช้งานได้กับ Bourne Shell บน Solaris แต่จริงๆแล้วทำงาน/bin/commandในกรณีนั้นซึ่งเป็นเชลล์ในตัวของ Bash)

ทั้งสอง/bin/commandและ/bin/envอยู่ในรายการ SUS ดังนั้นการใช้งานที่สอดคล้องทั้งหมดควรมี


envขอบคุณสำหรับการชี้ให้เห็น ผมอยู่ในความสงสัยซึ่งคำตอบที่ฉันควรจะยอมรับ แต่เนื่องจากเป็นคำถามที่เกี่ยวกับการทุบตีในตัวของมันcommandเป็นทางออกที่ดีที่สุด
Petr Pudlák

1
บนลีนุกซ์ของฉันไม่มีการcommandปฏิบัติการใด ๆ, แต่commandก็สามารถใช้งานได้dash, kshและzsh. ดังนั้นผมถือว่ามันเป็น builtin เปลือกไม่เพียง bashแต่ใน pastebin.com/fi3gyNse
จัดการ

มันไม่ได้เป็น buildin บน Solaris 10 Bourne (นั่นก็มีให้ใช้เหมือนมรดกสืบทอด) ข้อดีของการปฏิบัติการที่มีเส้นทางที่รู้จักคือมันไม่สามารถเขียนทับโดยฟังก์ชั่น
Gert van den Berg

(ไม่มี / bin / คำสั่งอาจอธิบายว่าทำไมสคริปต์ใช้/bin/envหลังจาก hash-bang หากพวกเขาไม่ต้องการโค้ดฮาร์พา ธ ของเชลล์อย่างหนัก)
Gert van den Berg

3

คำตอบของ Gert ทำให้ฉันรู้ว่ามีใครสามารถใช้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`.
Eliah Kagan

1
@EliahKagan ปัญหาที่เกิดขึ้น`which something`คือหากไม่มีการsomethingปฏิบัติการสิ่งที่โชคร้ายอาจเกิดขึ้นได้ ตัวอย่างเช่นหากechoขาดไปก็`which echo` /bin/rm preciousFileทำสิ่งที่แตกต่างจากที่ตั้งใจไว้มาก
Petr Pudlák
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.