ทำไมคุณต้อง. / (dot-slash) ก่อนที่จะปฏิบัติการหรือชื่อสคริปต์เพื่อรันในทุบตี?


288

เมื่อรันสคริปต์ใน bash ฉันต้องเขียน./ตอนแรก:

$ ./manage.py syncdb

หากฉันไม่ฉันได้รับข้อความแจ้งข้อผิดพลาด:

$ manage.py syncdb
-bash: manage.py: command not found

อะไรคือสาเหตุของสิ่งนี้? ฉันคิดว่า.เป็นนามแฝงสำหรับโฟลเดอร์ปัจจุบันดังนั้นการโทรทั้งสองนี้ควรเทียบเท่า

ฉันยังไม่เข้าใจด้วยว่าเหตุใดฉันจึงไม่ต้องการ./เมื่อเรียกใช้แอปพลิเคชันเช่น:

user:/home/user$ cd /usr/bin
user:/usr/bin$ git

(ซึ่งทำงานโดยไม่มี./)


4
นี่เป็นเอกสารที่ดีที่สุดในเรื่องที่ฉันเคยเจอมา: linfo.org/dot_slash.html
odigity

คำตอบ:


307

เพราะบน Unix $PATHปกติไดเรกทอรีปัจจุบันไม่ได้อยู่ใน

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

เหตุผลที่ไม่มีไดเรกทอรีปัจจุบันในรายการนั้นคือความปลอดภัย

สมมติว่าคุณกำลังรากและไปลงในไดเรกทอรีของผู้ใช้อื่นและพิมพ์แทนsl lsหากไดเรกทอรีปัจจุบันอยู่ในPATHเชลล์จะพยายามรันslโปรแกรมในไดเรกทอรีนั้น (เนื่องจากไม่มีslโปรแกรมอื่น) ว่าslโปรแกรมอาจเป็นอันตราย

มันทำงานร่วมกับ./เพราะPOSIX ระบุว่าชื่อคำสั่งที่มี/จะถูกใช้เป็นชื่อไฟล์โดยตรงยับยั้งการค้นหา$PATHมา คุณสามารถใช้เส้นทางแบบเต็มสำหรับเอฟเฟ็กต์แบบเดียวกัน แต่./สั้นกว่าและเขียนง่ายกว่า

แก้ไข

ที่slส่วนหนึ่งเป็นเพียงตัวอย่าง ไดเร็กทอรีในPATHจะถูกค้นหาตามลำดับและเมื่อทำการจับคู่แล้วโปรแกรมจะถูกเรียกใช้งาน ดังนั้นขึ้นอยู่กับว่าPATHลักษณะการพิมพ์คำสั่งปกติอาจหรืออาจไม่เพียงพอที่จะเรียกใช้โปรแกรมในไดเรกทอรีปัจจุบัน


47
คุณไม่จำเป็นต้องพิมพ์ผิด ผู้ใช้อาจเพิ่งดาวน์โหลดแพคเกจที่เป็นอันตรายซึ่งมีlsไฟล์ที่ปฏิบัติการได้
Juliano

13
แค่ให้ทุกคนบอกว่านี่เป็นเพียง Unix และไม่ใช่ Windows นี่ก็เหมือนกันใน Powershell - คุณต้องทำและ.\my.batอื่น ๆ เพื่อดำเนินการ
manojlds

1
@gaearon ergh ฉันพูดว่า "ไม่ใช่นามแฝง" เมื่อควรจะเป็น "เป็นนามแฝงอย่างเคร่งครัด"
Charles Duffy

4
นั่นเป็นคำอธิบายที่เป็นประโยชน์มาก 20+ ปีที่แล้วเมื่อฉันทำงานกับ DOS เพียงเล็กน้อยฉันคิดว่า CMD จะตรวจสอบไดเรกทอรีปัจจุบัน THEN the PATH ดังนั้นพฤติกรรมของ Linux จึงไม่ใช่สิ่งที่ฉันคาดหวัง แต่มันสมเหตุสมผลดี
TecBrat

2
@cnicutar: น่าสนใจวันนี้ฉันพบว่ามีslคำสั่งที่เรียกว่ารถจักรไอน้ำแม้ว่าจะไม่สามารถใช้ได้โดยค่าเริ่มต้น ;-)
blackSmith

51

$PATHเมื่อทุบตีตีความบรรทัดคำสั่งจะมองหาคำสั่งในสถานที่ที่ระบุไว้ในตัวแปรสภาพแวดล้อม เพื่อดูมันพิมพ์:

echo $PATH

คุณจะมีบางเส้นทางคั่นด้วยเครื่องหมายทวิภาค เป็นคุณจะเห็นเส้นทางปัจจุบันมักจะไม่ได้อยู่ใน. $PATHดังนั้น Bash ไม่สามารถหาคำสั่งของคุณได้หากมันอยู่ในไดเรกทอรีปัจจุบัน คุณสามารถเปลี่ยนได้โดย:

PATH=$PATH:.

บรรทัดนี้เพิ่มไดเรกทอรีปัจจุบัน$PATHเพื่อที่คุณจะได้:

manage.py syncdb

มันเป็นเรื่องที่ไม่ได้แนะนำตามที่มีปัญหาด้านความปลอดภัยรวมทั้งคุณสามารถมีพฤติกรรมแปลก ๆ เช่น.แตกต่างกันเมื่อไดเรกทอรีที่คุณอยู่ใน :)

ควรหลีกเลี่ยง:

PATH=.:$PATH

ในขณะที่คุณสามารถ "ปกปิด" คำสั่งมาตรฐานและเปิดประตูสู่การละเมิดความปลอดภัย :)

แค่สองเซ็นต์ของฉัน


42

สคริปต์ของคุณเมื่ออยู่ในโฮมไดเรกทอรีของคุณจะไม่ถูกค้นพบเมื่อเชลล์พิจารณา$PATHตัวแปรสภาพแวดล้อมเพื่อค้นหาสคริปต์ของคุณ

เครื่องหมาย./ว่า 'ดูในไดเรกทอรีปัจจุบันของสคริปต์ของฉันแทนที่จะดูไดเรกทอรีทั้งหมดที่ระบุใน$PATH'


5

เมื่อคุณรวม '.' คุณกำลังให้ "เต็มเส้นทาง" แก่สคริปต์ทุบตีปฏิบัติการดังนั้นเชลล์ของคุณไม่จำเป็นต้องตรวจสอบตัวแปร PATH ของคุณ ปราศจาก '.' เชลล์ของคุณจะดูในตัวแปร PATH ของคุณ (ซึ่งคุณสามารถดูได้ด้วยการรันecho $PATHเพื่อดูว่าคำสั่งที่คุณพิมพ์อยู่ในโฟลเดอร์ใด ๆ บน PATH ของคุณหรือไม่ถ้าไม่ (เช่นกรณีที่มี Manage.py) ไม่สามารถค้นหาไฟล์ได้ถือว่าเป็นการปฏิบัติที่ไม่ถูกต้องที่จะรวมไดเรกทอรีปัจจุบันบน PATH ของคุณซึ่งได้รับการอธิบายอย่างมีเหตุผลที่นี่: http://www.faqs.org/faqs/unix-faq/fa2/part2/section- 13.html


2

บน * ระวังซึ่งแตกต่างจาก Windows ไดเรกทอรีปัจจุบันมักจะไม่อยู่ใน$PATHตัวแปรของคุณ ดังนั้นไดเรกทอรีปัจจุบันจะไม่ถูกค้นหาเมื่อดำเนินการคำสั่ง คุณไม่จำเป็นต้อง./ใช้แอปพลิเคชันเพราะแอปพลิเคชันเหล่านี้อยู่ใน $ PATH ส่วนใหญ่มีแนวโน้มจะเป็นในหรือ/bin/usr/bin


1

คำถามนี้มีคำตอบที่ยอดเยี่ยมอยู่แล้ว แต่ฉันต้องการเพิ่มถ้าปฏิบัติการของคุณอยู่บน PATH และคุณได้รับผลลัพธ์ที่แตกต่างกันมากเมื่อคุณรัน

./executable

กับสิ่งที่คุณได้รับถ้าคุณวิ่ง

executable

(สมมติว่าคุณพบข้อความแสดงข้อผิดพลาดกับอีกรายการหนึ่ง) จากนั้นปัญหาอาจเกิดขึ้นได้ว่าคุณมีรุ่นที่เรียกใช้งานได้สองเวอร์ชันในเครื่องของคุณ: หนึ่งรายการบนเส้นทางและอีกรุ่นหนึ่งไม่ใช่

ตรวจสอบสิ่งนี้ด้วยการวิ่ง

สิ่งที่ปฏิบัติการได้

และ

whereis executable

มันแก้ไขปัญหาของฉัน ... ฉันมีไฟล์ปฏิบัติการสามเวอร์ชันซึ่งหนึ่งไฟล์ถูกคอมไพล์อย่างถูกต้องสำหรับสภาพแวดล้อม


0

เหตุผลสำหรับ/กฎ POSIX PATH

กฎถูกกล่าวถึงที่: ทำไมคุณต้อง. / (dot-slash) ก่อนที่จะปฏิบัติการหรือชื่อสคริปต์เพื่อเรียกใช้ในทุบตี? แต่ฉันอยากจะอธิบายว่าทำไมฉันถึงคิดว่ามันเป็นรายละเอียดที่ดีมาก

อันดับแรกกฎเวอร์ชันเต็มอย่างชัดเจนคือ:

  • ถ้าเส้นทางประกอบด้วย/(เช่น./someprog, /bin/someprog, ./bin/someprog): CWD และใช้เส้นทางไม่
  • หากเส้นทางไม่มี/(เช่นsomeprog): ใช้เส้นทางและ CWD ไม่ได้

ตอนนี้สมมติว่าการทำงาน:

someprog

จะค้นหา:

  • สัมพันธ์กับ CWD ก่อน
  • สัมพันธ์กับ PATH หลังจาก

จากนั้นหากคุณต้องการหนี/bin/someprogจากความวุ่นวายและคุณได้:

someprog

บางครั้งอาจใช้งานได้ แต่บางโปรแกรมอาจล้มเหลวเนื่องจากคุณอาจอยู่ในไดเรกทอรีที่มีsomeprogโปรแกรมอื่นที่ไม่เกี่ยวข้อง

ดังนั้นในไม่ช้าคุณจะได้เรียนรู้ว่าสิ่งนี้ไม่น่าเชื่อถือและคุณจะจบลงด้วยการใช้พา ธ สัมบูรณ์เมื่อคุณต้องการใช้ PATH ดังนั้นการเอาชนะวัตถุประสงค์ของ PATH

นี่คือสาเหตุที่การมีเส้นทางสัมพัทธ์ใน PATH ของคุณเป็นความคิดที่แย่จริงๆ ฉันมองไปที่คุณnode_modules/bin

ในทางกลับกันสมมติว่าการทำงาน:

./someprog

จะค้นหา:

  • สัมพันธ์กับ PATH ก่อน
  • สัมพันธ์กับ CWD หลัง

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

/bin/someprog

ซึ่งอยู่ในเส้นทางของคุณจากแพคเกจที่คุณติดตั้งหลังจากดื่มมากเกินไปหลังจากคริสต์มาสปีที่แล้ว

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

"$(pwd)/someprog"

ซึ่งจะน่ารำคาญอย่างยิ่งเช่นกัน

กฎอีกข้อที่คุณอาจถูกล่อลวงให้คิดขึ้นมาคือ:

พา ธ สัมพันธ์ใช้ PATH เท่านั้น, พา ธ สัมบูรณ์เท่านั้น CWD

"$(pwd)/someprog"แต่อีกครั้งนี้ผู้ใช้กองกำลังที่จะมักจะใช้เส้นทางที่แน่นอนสำหรับสคริปต์ที่ไม่ใช่เส้นทางที่มี

/กฎการค้นหาเส้นทางให้บริการที่ง่ายต่อการจดจำวิธีการแก้ปัญหาเกี่ยวกับ:

  • เครื่องหมายทับ: ไม่ต้องใช้ PATH
  • ไม่ทับ: ใช้เฉพาะ PATH

ซึ่งทำให้มันง่ายมากที่จะรู้ว่าคุณกำลังใช้งานอะไรอยู่เสมอโดยอาศัยความจริงที่ว่าไฟล์ในไดเรกทอรีปัจจุบันสามารถแสดงเป็น./somefileหรือsomefileดังนั้นจึงให้ความหมายพิเศษกับหนึ่งในนั้น

บางครั้งน่ารำคาญเล็กน้อยที่คุณไม่สามารถค้นหาsome/progความสัมพันธ์ได้PATHแต่ฉันไม่เห็นวิธีแก้ปัญหาที่ถูกต้อง


-1

เมื่อสคริปต์ไม่ได้อยู่ใน Path ต้องทำเช่นนั้น สำหรับข้อมูลเพิ่มเติมอ่านhttp://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_01.html


5
... FYI ใน #bash บน irc.freenode.org เรากำลังแก้ไขความเข้าใจผิดที่ผู้คนเรียนรู้จาก TLDP อย่างต่อเนื่อง (โดยเฉพาะคู่มือการทุบตีขั้นสูง) ดังนั้นการกำกับผู้คนที่นั่น ... อาจไม่เหมาะ (เอกสารแนะนำเบื้องต้นที่เราต้องการคือmywiki.wooledge.org/BashGuide )
Charles Duffy

-2

ทุกคนมีคำตอบที่ดีสำหรับคำถามและใช่สิ่งนี้ใช้ได้เฉพาะเมื่อเรียกใช้ในไดเรกทอรีปัจจุบันเท่านั้นเว้นแต่คุณจะใส่เส้นทางที่แน่นอน ดูตัวอย่างของฉันด้านล่าง

นอกจากนี้ (dot-slash) ก็สมเหตุสมผลกับฉันเมื่อฉันได้รับคำสั่งในโฟลเดอร์ลูก tmp2 (/ tmp / tmp2) และมันใช้ (double dot-slash)

ตัวอย่าง:

[fifiip-172-31-17-12 tmp]$ ./StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ /tmp/StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ mkdir tmp2

[fifi@ip-172-31-17-12 tmp]$ cd tmp2/

[fifi@ip-172-31-17-12 tmp2]$ ../StackO.sh

Hello Stack Overflow
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.