ฉันจะหาเส้นทางแบบเต็มของโปรแกรมบนเส้นทางได้อย่างน่าเชื่อถือได้อย่างไร


12

ฉันต้องการค้นหาเส้นทางของโปรแกรมที่กำหนดในการPATHใช้เชลล์สคริปต์ เส้นทางที่จะต้องเป็นเส้นทางจริงเต็มรูปแบบของโปรแกรมซึ่งสามารถส่งผ่านต่อมาหนึ่งในexec*ฟังก์ชั่นที่ไม่ได้ค้นหาตัวเองเช่นPATHexecv

มีโปรแกรมเช่นkillซึ่งมีให้เป็นโปรแกรมจริงและเชลล์ในตัวในเวลาเดียวกัน หากเป็นกรณีนี้ฉันต้องการเส้นทางแบบเต็มไปยังโปรแกรมจริง

มีสาธารณูปโภคหลายอย่างที่สามารถหาโปรแกรมบนเป็นPATHตามที่ระบุไว้ในมาตรา 2.9.1.1 คำสั่งค้นหาและการดำเนินการของมาตรฐาน

มีwhichซึ่งไม่ได้เป็นส่วนหนึ่งของมาตรฐานใด ๆ มันสามารถเป็นโปรแกรมปกติในบางระบบในขณะที่บางเชลล์ให้มันเป็น builtin ดูเหมือนว่าจะมีอยู่ในระบบและเชลล์ส่วนใหญ่ แต่เชลล์ที่มีเวอร์ชันในตัวก็แค่ส่งคืนชื่อของบิวด์อินแทนที่จะเป็นพา ธ ไปยังไฟล์ที่เรียกใช้งานได้ นอกจากนี้ยังไม่ได้มาตรฐานในทางใดทางหนึ่งและอาจส่งคืนผลลัพธ์ใด ๆ และใช้ตัวเลือกที่แตกต่างกัน

bash# which kill
/usr/bin/kill
dash# which kill
/usr/bin/kill
fish# which kill
/usr/bin/kill
mksh# which kill
/usr/bin/kill
tcsh# which kill
kill: shell built-in command.
zsh# which kill
kill: shell built-in command

มีwhenceซึ่งเป็นในตัวของเปลือกหอยไม่กี่คน แต่ไม่สามารถใช้ได้กับกระสุนจำนวนมาก มันก็จะกลับชื่อของในตัวแทนเส้นทางไปยังโปรแกรม -pอาจจะส่งผ่านไปยังมาจากไหนที่จะเปลี่ยนพฤติกรรมนี้

bash# whence kill
bash: whence: command not found
dash# whence kill
dash: 1: whence: not found
fish# whence kill
fish: Unknown command 'whence'
mksh# whence kill
kill
mksh# whence -p kill
/usr/bin/kill
tcsh# whence kill
whence: Command not found.
zsh# whence kill
kill
zsh# whence -p kill
/usr/bin/kill

มีเป็นcommandbuiltin ระบุโดย POSIX: น่าเสียดายที่มันยังค้นหาคำสั่งปกติและบิวด์อินและจะส่งคืนชื่อของบิวด์อินแทนพา ธ ไปยังโปรแกรมที่แชโดว์โดยบิวด์อินที่มีชื่อเดียวกัน เชลล์เก่าบางตัวยังไม่ได้ใช้งาน

bash# command -v kill
kill
dash# command -v kill
kill
fish# command -v kill
/usr/bin/kill
mksh# command -v kill
kill
tcsh# command -v kill
command: Command not found.
zsh# command -v kill
kill

ฉันไม่สามารถคิดออกว่าenableมีการระบุใน POSIX หรือไม่ แต่ถ้ามันเป็นคุณสามารถใช้เพื่อปิดการใช้เปลือกในตัวสำหรับenable -n which which
Muzer

และมีrealpath
Ipor Sircer

@ Muzer บนเปลือกหอยที่ฉันมีให้ฉันenableมีให้โดยbashและzsh
Sebastian Schrader

2
คุณต้องการวิธีการที่ใช้งานได้จริงสำหรับเชลล์เฉพาะที่รันสคริปต์ของคุณไม่ใช่เชลล์ทั้งหมด สคริปต์ไม่ได้ถูกดำเนินการโดยเชลล์สุ่ม แต่โดยเฉพาะเชลล์ที่ระบุในบรรทัด shebang type -pที่ถูกกล่าวว่าในทุบตีที่จะเป็น ทั้ง bash และ dash ให้คุณบอกว่าcommandcommand ให้เรียกใช้ปฏิบัติการจริงได้แม้ว่าจะมีฟังก์ชั่นหรือ builtin ที่มีชื่อเหมือนกันก็ตาม
AlexP

1
@AlexP commandข้ามฟังก์ชั่น (และนามแฝง) แต่ไม่ใช่ builtins ตามที่ Q พูดอย่างถูกต้อง และคุณไม่สามารถใช้ shebang ได้ตลอดเวลาเพราะไม่มีเส้นทางที่ได้รับเชลล์ใด ๆ หรือแม้แต่ POSIX เชลล์บางตัวในทุกระบบ
dave_thompson_085

คำตอบ:


11

เพียงค้นหาด้วยตัวคุณเอง

export IFS=":"
[ -z "${1}" ] && exit 1
for dir in $PATH
do if [ -x "${dir}/${1}" ]
   then echo "${dir}/${1}"
        exit 0
   fi
done
echo ${1} not found
exit 1

การทดสอบในbash, dash, ksh, mksh,zsh

ปรับปรุง

ด้านบนเป็นสิ่งที่ดีสำหรับสคริปต์แบบสแตนด์อะโลน แต่ถ้าคุณวางแผนที่จะฝังลงในสคริปต์ที่มีขนาดใหญ่ขึ้นคุณอาจต้องการใช้สิ่งต่อไปนี้

function find_path() {
   IFS_SAVE="${IFS}"
   export IFS=":"
   [ -z "${1}" ] && return 1
   for dir in $PATH
   do if [ -x "${dir}/${1}" ]
      then echo "${dir}/${1}"
           export IFS="${IFS_SAVE}"
           return 0
      fi
   done
   export IFS="${IFS_SAVE}"
   echo ${1} not found
   return 1
}

นี่คือเพื่อที่IFSจะคืนค่าหลังจากพบการแข่งขันยังสลับexitกับreturnของ


1
อาจจะ -x แทน -f?
Jeff Schaller

@JeffSchaller จุดดีไม่มีเหตุผลที่จะเลือกไฟล์ที่ไม่สามารถใช้งานได้
Zachary Brady

3
หากคุณรวมสิ่งนี้ลงในเชลล์สคริปต์ที่มีขนาดใหญ่ขึ้น (ซึ่งแตกต่างจากการทำให้เป็นสคริปต์ในสิทธิของตนเองตามที่ตั้งใจไว้) คุณอาจต้องการเรียกคืนค่าเก่าของ IFS หลังจากนั้น - มิฉะนั้นอาจมีผลกระทบมากมาย สคริปต์ที่เหลือ ...
psmears

ทำไมส่งออกIFSตัวแปร มันไม่พอที่จะมีชุดนี้ในเปลือกท้องถิ่น? การพูดของท้องถิ่นจะlocal IFSพกพา? ด้านบนอาจมีผลกระทบไม่ดีหากมีสิ่งอื่นที่ช่วย IFS ในลักษณะเดียวกัน มองไปที่คำถามนี้ใน SE , localอาจทำงานสำหรับเปลือกหอยมากที่สุดแม้จะไม่เป็น POSIX การวางเวอร์ชันดั้งเดิมไว้ใน(…)เชลล์ย่อยอาจทำงานได้เช่นกัน
MvG
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.