Linux จัดการตัวคั่นพา ธ หลายตัวต่อเนื่องกันอย่างไร (ไฟล์ / home //// ชื่อผู้ใช้ ///)?


111

ฉันกำลังทำงานกับสคริปต์หลามที่ส่งผ่านตำแหน่งไฟล์ไปยังกระบวนการย่อย scp ไม่เป็นไร แต่ฉันอยู่ในสถานการณ์ที่ฉันอาจจะต่อท้ายชื่อพา ธ ที่มีชื่อไฟล์ว่ามีสองครั้ง/ในเส้นทาง ฉันรู้ว่าทุบตีไม่สนใจว่าคุณมีหลายตัวคั่นไฟล์ แต่ฉันสงสัยว่ามันถูกแก้ไข มันทุบตีที่แถบพิเศษ/หรือมันไม่สำคัญว่าเคย?

ฉันถามเพราะมันจะช่วยฉันรหัสหลายบรรทัดเพื่อตรวจสอบ/s พิเศษในขณะที่เรียงต่อกัน ฉันรู้ว่ามันไม่ใช่เรื่องใหญ่ แต่ฉันก็อยากรู้อยากเห็นเช่นกัน ฉันมีสคริปต์ทุบตีที่มีบรรทัดcd //usr(แทนcd /usr) ซึ่งดูเหมือนจะบอกเป็นนัยว่าอาจมีความสำคัญในการใช้หลาย/s ในเส้นทาง


7
ฉันต้องการลงทุนในสายพิเศษของรหัส ...
สเตฟาน

5
ในกรณีที่ทุกคนใส่ใจซึ่งฉันแน่ใจว่าไม่มีใครทำฉันจริง ๆ แล้วท้ายที่สุดใช้ python joinและabspathคำสั่งดังกล่าว
Falmarri

คำตอบ:


165

อนุญาตให้ใช้หลายสแลชและเทียบเท่ากับสแลชเดี่ยว จากข้อกำหนด Unix เดี่ยว (รุ่น 3) , ข้อกำหนดพื้นฐาน§3.266ชื่อพา ธ :“ ทับต่อเนื่องหลายรับการพิจารณาให้เป็นเช่นเดียวกับหนึ่งเฉือน”

มีข้อยกเว้นคือถ้าชื่อพา ธ เริ่มต้นด้วยตรงสองทับก็อาจจะถือว่าแตกต่างกัน (Ref: ฐานนิยาม§4.11ความละเอียดชื่อพา ธ ) Linux เองนั้นไม่ได้ทำสิ่งนี้ถึงแม้ว่าบางแอพพลิเคชั่นอาจและระบบ unix-ish อื่น ๆ (เช่น Cygwin)

การติดตาม/ที่ส่วนท้ายของชื่อพา ธ จะบังคับให้ชื่อพา ธ อ้างอิงถึงไดเรกทอรี ใน ( POSIX 1,003.1-2,001 (Single v3 Unix) ฐานนิยามความละเอียด§4.11ชื่อพา ธ , ต่อท้าย/จะเทียบเท่ากับการต่อท้าย/.. POSIX 1,003.1-2,008 (Unix เดี่ยวนิยาม v4) ฐาน§4.12เอาความต้องการที่จะทำให้มันเทียบเท่ากับ/.ในการสั่งซื้อ เพื่อจัดการกับไดเรกทอรีที่ไม่มีอยู่ (เช่นmkdir foo/จำเป็นต้องทำงานในขณะที่mkdir foo/.ไม่เห็นเหตุผลสำหรับการเปลี่ยนแปลง)

สำหรับโปรแกรมที่ทำหน้าที่ในรายการไดเรกทอรีถ้าfooเป็นลิงก์สัญลักษณ์ไปยังไดเรกทอรีการส่งผ่านfoo/เป็นวิธีที่ทำให้โปรแกรมดำเนินการกับไดเรกทอรีแทนที่จะเป็นลิงก์สัญลักษณ์

¹ โปรดทราบว่าสิ่งนี้ใช้สำหรับการแก้ปัญหาชื่อพา ธ เท่านั้นเช่นเมื่อเข้าถึงไฟล์ การเปลี่ยนชื่อไฟล์อาจทำงานแตกต่างกัน ตัวอย่างbasenameและdirnameละเว้นเครื่องหมายทับต่อท้าย


7
ข้อมูลที่เทียบเท่า/.ได้ถูกลบออกหลังจากกระบวนการอภิปรายในภายหลังเนื่องจากไม่ชัดเจน อย่างไรก็ตาม +1 เนื่องจากการหาข้อมูลประเภทนี้ที่สรุปได้ดีนั้นเป็นเรื่องยาก
hakre

17

ระบบปฏิบัติการไม่ได้สนใจอะไรเลยเมื่อลองใช้โปรแกรม C ที่มี syscall โดยตรงเพื่อเปิดด้วย // ในพา ธ

คุณสามารถใช้ฟังก์ชั่นห้องสมุดหลาม os.path.normpath เพื่อทำให้ปกติได้ซึ่งช่วยให้คุณไม่ต้องสแกนผ่านสตริงเพื่อค้นหาสิ่งพิเศษ ภาษาอื่นมีฟังก์ชั่นที่คล้ายกัน

http://docs.python.org/library/os.path.html#os.path.normpath


5
ระวังความคิดเห็นต่อไปนี้ในแหล่งที่มาของ normpath: ทำให้เส้นทางเป็นปกติเช่น A // B, A /./ B และ A / foo /../ B ทั้งหมดกลายเป็น A / B ควรเข้าใจว่าสิ่งนี้อาจเปลี่ยนความหมายของเส้นทางหากมีลิงก์สัญลักษณ์!
Bluehorn

8

ในทุกระบบ Unix ที่ฉันเห็นมันเป็นระบบเดียว/แต่มาตรฐาน Unixระบุว่า

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

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


7
Cygwin (ในขณะที่ไม่ได้เป็นจริง UNIX) ไม่แปล//remote/...เพื่อการเข้าถึงระบบไฟล์ระยะไกลอาจจะสอดคล้องกับ Windows' \\remote\...
ephemient

2
ฉันเชื่อว่า (แต่ Google ไม่สามารถอ้างอิงที่ดีได้ในขณะนี้) ว่า API ของ Windows POSIX compat APIs จะปฏิบัติ//remote/...เช่นเดียวกันกับ\\remote\...รูปแบบเส้นทาง UNC
สตีเฟ่น P

1
ฉันคิดว่าฉันจำได้ว่าชื่อพา ธ แบบพกพาของ Boost.Files ระบบจัดการ//ในวิธีพิเศษในการที่พวกเขาอาจทดสอบfalseการเป็นสัมบูรณ์ตามมาตรฐาน Unix / POSIX

7

ใช้os.path.joinใน Python และคุณจะไม่ได้รับเครื่องหมายทับหลายอัน การสร้างชื่อไฟล์ด้วยตัวคุณเองโดยการต่อสตริงถือว่าเป็นสไตล์ Python ที่ไม่ดี


ฉันเห็นด้วย แต่ชื่อไฟล์เป็นส่วนหนึ่งของสตริงคำสั่งและแทนที่จะแยกวิเคราะห์สตริงคำสั่งเพื่อต่อท้ายชื่อไฟล์ (ในตอนท้าย) ฉันแค่ต้องการต่อท้าย
Falmarri

1
@Falmarri: คุณไม่สามารถเพิ่มชื่อไฟล์ลงในสตริงคำสั่งต่อท้ายได้! สตริงคำสั่งจะถูกวิเคราะห์คำโดยเชลล์ดังนั้นต้องใช้อักขระพิเศษในชื่อไฟล์ ดังนั้นคุณต้องสร้างชื่อไฟล์จากนั้นอ้างอย่างถูกต้องเพื่อใส่ลงในสตริงคำสั่ง
Gilles

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

1
@Falmarri: ดังนั้นใช้ normpath เพื่อล้างค่าบรรทัดคำสั่งที่คุณไม่ได้ควบคุมจากนั้นใช้การเข้าร่วมเพื่อรวมเข้าด้วยกัน
Neil Mayhew

นี่คือสิ่งที่ฉันทำ = \ ฉันไม่สามารถรับมือกับกรณีพิเศษที่ฉันได้รับ/ดีมาก
Falmarri

3

ไม่มีความแตกต่าง

เครื่องหมายทับหลายอันจะถูกละเว้น (โดยไม่มีผลกระทบ) เช่น:

ls -al //usr///////bin/sed

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

ขอบคุณคริสฉันขอขอบคุณการชี้แจง! (น่าเสียดายที่การเข้าสู่ระบบ OpenID ไม่ทำงานสำหรับฉันหรือฉันจะลงคะแนนให้คุณ)

@Rob คุณยังไม่ได้ลงทะเบียน แต่ยังอยู่ในระบบ (คุณถูกติดตามโดยคุกกี้ของคุณ) คุณควรลงทะเบียนตอนนี้เพื่อเชื่อมต่อ OpenID กับบัญชีของคุณ แต่คุณสามารถลงคะแนนได้ทั้งสองวิธี
Michael Mrozek

ขอบคุณ Michael แต่ "คุณต้องเข้าสู่ระบบหรือลงทะเบียนเพื่อลงคะแนน" เมื่อคุณใช้ที่อยู่อีเมลและชื่อคุณจะไม่มีสิทธิ์เต็มที่ และเนื่องจาก OpenID หมดเวลาและฉันไม่รู้สึกอยากสร้างบัญชีอื่นฉันจึงโชคไม่ดี ความผิดของฉันในการเป็นคนขี้เกียจฉันเดา แต่ฉันซาบซึ้งในความช่วยเหลือ

0

แน่นอนว่าคุณสามารถทำให้เส้นทางเป็นปกติด้วยหลาย / (เครื่องหมายทับ) ที่เป็นไปได้โดยผ่านไป tr -s

NORMALIZED=$(echo "$UNHYGIENIC" | tr -s / /)

... และจากนั้นใช้ $NORMALIZED

อย่างไรก็ตามควรมีความจำเป็น สำหรับที่ฉันรู้เคอร์เนล UNIX ถูกต้องควรละเว้นตัวคั่นเส้นทางพร้อมกัน --- หรือแนวคิดการรักษาพวกเขาเป็น/./...


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