ฉันจะทดสอบเพื่อดูว่ามีแอปพลิเคชันอยู่ใน $ PATH ได้อย่างไร


19

ฉันพยายามที่จะเขียนshสคริปต์เริ่มต้น / env ทั้งหมดของฉันเพื่อทำงานกับDRYให้มากที่สุดเท่าที่จะเป็นไปได้: "ใช้ได้กับทุก ๆ * * * * * * * * * * * * * * * * * * * * * * * นี่หมายถึงการทำให้แน่ใจว่าถ้าฉันพยายามเรียกใช้รหัสที่ไม่มีอยู่นั้นรหัสนั้นจะล้มเหลวอย่างงดงาม ด้วยเหตุนี้ฉันต้องสามารถทดสอบว่ามีโปรแกรมอยู่หรือไม่ ฉันรู้วิธีทดสอบว่ามีไฟล์อยู่หรือไม่ แต่ฉันไม่แน่ใจว่าจะทดสอบอย่างไรเพื่อดูว่าแอปพลิเคชันสามารถทำงานได้ภายในพา ธ หรือไม่ ฉันควรใช้ $ PATH เนื่องจากบางส่วนของสิ่งเหล่านี้จำเป็นต้องใช้กับ arch, ubuntu และ centos บางระบบอาจถูกติดตั้งในบ้านของฉันในระบบที่ฉันไม่มีรูทและบางระบบอาจไม่ได้ติดตั้งและอื่น ๆ ที่ติดตั้งในพา ธ ของระบบ


2
คำตอบ SOนี้เป็นคำตอบที่ฉันบุ๊คมาร์คไว้สำหรับคำถามเหล่านี้
jw013

คำตอบ:


19

type commandnameใช้ สิ่งนี้จะคืนค่าเป็นจริงหากcommandnameมีสิ่งใดที่สามารถดำเนินการได้: นามแฝง, ฟังก์ชัน, คำสั่งในตัวหรือภายนอก (ค้นหาใน$PATH) อีกทางเลือกหนึ่งคือใช้คำสั่งcommand commandnameส่งคืนค่าจริงถ้าcommandnameเป็นคำสั่งในตัวหรือภายนอก (ค้นหาใน$PATH)

exists () {
  type "$1" >/dev/null 2>/dev/null
}

มีตัวแปร SH หลายตัว (แน่นอนก่อน POSIX; ฉันรู้/bin/shภายใต้ OSF1 ≤3.xและเชลล์ Almquist บางรุ่นที่พบใน NetBSD รุ่นแรกและการกระจาย Linux ในศตวรรษที่ 20) ซึ่งtypeส่งคืน 0 เสมอหรือไม่ ที่มีอยู่ ฉันไม่คิดว่าระบบใด ๆ ที่ส่งมาพร้อมกับสหัสวรรษนี้ หากคุณเคยพบพวกเขานี่เป็นฟังก์ชั่นที่คุณสามารถใช้ค้นหา$PATHด้วยตนเอง:

exists () { (
    IFS=:
    for d in $PATH; do
      if test -x "$d/$1"; then return 0; fi
    done
    return 1
) }

ฟังก์ชั่นนี้จะเป็นประโยชน์โดยทั่วไปถ้าคุณต้องการที่จะไม่รวมตัว -ins $PATHและฟังก์ชั่นและมองขึ้นชื่อใน เชลล์ส่วนใหญ่มี built-in สำหรับสิ่งนี้command -vถึงแม้ว่ามันจะเป็นส่วนเสริมล่าสุดของ POSIX (ยังเป็นตัวเลือก ณ วันที่ POSIX: 2004) โดยพื้นฐานแล้วมันเป็นเวอร์ชันที่เหมาะสำหรับโปรแกรมเมอร์ซึ่งtypeจะพิมพ์เส้นทางแบบเต็มสำหรับการเรียก$PATHใช้งานได้ชื่อเปล่าสำหรับบิวด์อินหรือฟังก์ชันและคำจำกัดความของนามแฝงสำหรับนามแฝง

exists_in_path () {
  case $(command -v -- "$1") in
    /*) return 0;;
    alias\ *) return 1;; # alias
    *) return 1;; # built-in or function
  esac
}

ksh, ทุบตีและ zsh ยังมีtype -pที่จะมองขึ้นเพียง executables $PATHใน โปรดทราบว่าในทุบตีสถานะการส่งคืนtype -p fooเป็น 0 ถ้าfooเป็นในตัวหรือฟังก์ชั่น; ถ้าคุณต้องการทดสอบการปฏิบัติการ$PATHคุณต้องตรวจสอบว่าเอาต์พุตไม่ว่างเปล่า type -pไม่ได้อยู่ใน POSIX; เช่น Debian's ash (ซึ่งอยู่/bin/shใน Ubuntu) ไม่มีอยู่


@gilles สิ่งนี้ (หรือสิ่งที่คล้ายกัน) จะif [ type keychain ]; thenไม่ทำงานหรือไม่ ฉันได้รับข้อผิดพลาด/home/xenoterracide/.zshrc:84: parse error: condition expected: typeฉันคิดว่าฉันสามารถเขียนฟังก์ชั่นที่มีอยู่ได้ ... ฉันแค่คิดว่ามันอาจจะง่ายกว่านี้ ...
xenoterracide

@xenoterracide: วางวงเล็บ!
Gilles 'หยุดชั่วร้าย'

ฉันคิดว่าคุณกำลังมองหาคุณไม่ต้องการif type $APP >/dev/null 2>/dev/null; then ... []
Steven D

4
Bah ฉันรู้ว่าฉันควรจะรีเฟรช พ่ายแพ้โดย Gilles อีกครั้ง!
Steven D

type -pหากคุณกำลังมองหาคำสั่งเฉพาะใน$PATH(ไม่ใช่นามแฝงหรือฟังก์ชั่นหรือ builtins)
ephemient

1

หากคุณกำลังมองหาโปรแกรมภายนอกคุณสามารถใช้โปรแกรมใด แต่ไม่รู้ว่าพกพาไปได้อย่างไร


3
ในทางทฤษฎีมันพกพาได้น้อยกว่าtypeหรือcommand; whichไม่ได้อยู่ใน POSIX เป็นต้น ในทางปฏิบัติwhichมีอยู่เกือบทุกที่ แต่ในบางสถานที่ (ซึ่งมีการนำไปใช้เป็นสคริปต์ csh) จะใช้เส้นทางที่แตกต่างกัน (เนื่องจาก a .cshrc) ซึ่งเอาชนะวัตถุประสงค์
Gilles 'หยุดชั่วร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.