ลิงก์สัญลักษณ์ไปยังไดเร็กทอรีและพา ธ สัมพัทธ์


15

ฉันได้สร้าง symlink ด้วยเส้นทางที่แน่นอนไปยังไดเรกทอรี (กะพริบ) และมีตัวอย่างดังต่อไปนี้ต้นไม้:

$ ls -l /tmp/A
total 0
lrwxrwxrwx 1 root root 6 Apr  3 12:27 Blink -> /tmp/B
-rw-r--r-- 1 root root 0 Apr  3 12:27 foo

$ ls -l /tmp/B
total 0
-rw-r--r-- 1 root root 0 Apr  3 12:27 bar

จากนั้นฉันไปที่ / tmp / A และเปลี่ยนไดเรกทอรีเป็น Blink:

$ cd /tmp/A
$ pwd
/tmp/A
$ cd Blink
$ pwd
/tmp/A/Blink

cd ..กลับไปที่ฉัน/tmp/A แต่ถ้าฉันพิมพ์เช่นls ../fooฉันจะได้รับข้อผิดพลาด:

ls: ../foo: No such file or directory

คำสั่ง builtin cd แก้ไขพา ธ ได้ตามต้องการ แต่ภายนอก ls พิจารณา .. เป็น up-level ของ / tmp / B ดังนั้นจึงไม่พบ foo

ปัญหาคืออะไรที่นี่? ฉันสามารถรับไฟล์ foo จาก / tmp / A / Blink โดยพา ธ สัมพัทธ์เช่น ../foo ได้ไหม?


คำถามเดียวกันถูกข้ามโพสต์บนSuperUser
Peter.O

คำตอบ:


13

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

แต่เมื่อคุณทำงานls ../foo, lsไม่ทราบว่าเปลือกมีการไดเรกทอรีโดยต่อไปนี้การเชื่อมโยงสัญลักษณ์ lsจะทำstat()ใน "../foo" ส่วน ".. " มาจากไดเรกทอรีปัจจุบันซึ่งมีรายการ ".. " เพียงรายการเดียวสำหรับรายการหลัก สิ่งที่ลิงก์สัญลักษณ์ทั้งหมดไม่เปลี่ยนวิธีที่ไดเรกทอรีมี "" เพียงอย่างเดียว และรายการ ".. " เดี่ยว ลิงก์สัญลักษณ์อนุญาตให้เคอร์เนลแทรกเลเยอร์ทางอ้อมพิเศษลงในพา ธ ไฟล์ เมื่อคุณส่ง "../wh สิ่ง" ไปยังopen()หรือstat()เคอร์เนลเพียงใช้ไดเรกทอรีการทำงานปัจจุบันของกระบวนการที่ทำการเรียกเพื่อคิดออกว่าไดเรกทอรีเดียวชื่อ ".. "


17

เชลล์เก็บไดเร็กทอรีการทำงานปัจจุบัน$PWDไว้ นั่นคือสิ่งที่ใช้สำหรับ builtins เปลือกcdและpwdและมันถือว่า symlinks ไดเรกทอรีปกติที่สุดเท่าที่คุณเคยเห็น บางครั้งสิ่งนี้มีประโยชน์บางครั้งไม่

คุณสามารถค้นหาไดเรกทอรีจริงโดยใช้pwd(พิมพ์help pwdเพื่อดูรายละเอียดเพิ่มเติม):

$ pwd
/tmp/A/Blink
$ pwd -L
/tmp/A/Blink
$ pwd -P
/tmp/B

ในทำนองเดียวกันcdมีตัวเลือก-P(อีกครั้งhelp cdคือเพื่อนของคุณ):

$ cd /tmp/A/Blink
$ pwd
/tmp/A/Blink
$ cd -P ..
$ pwd -P
/tmp

สุดท้ายคุณสามารถปิด "ฟีเจอร์" ทั้งหมด:

$ set -P
$ cd /tmp/A/Blink
$ pwd
/tmp/B

ขอบคุณฉันรู้เกี่ยวกับคุณสมบัติการตั้งค่า -P แต่สับสนโดยพฤติกรรมคำสั่ง ls ...
user478681

อย่างที่ฉันพูดการใช้งานset -Pและพฤติกรรม ls เริ่มมีเหตุผล :)
ams

2

บรูซและ ams ให้คำตอบที่สวยงามเพื่ออธิบายพฤติกรรมที่อยู่เบื้องหลัง แต่จริงๆแล้วสิ่งที่ls ../fooคุณถามคุณสามารถไปกับสิ่งที่ชอบ

ls $(dirname $PWD)/foo

1

คุณไม่สามารถทำมันเพราะ/tmp/A/Blink เป็น/tmp/Bจริง ดังนั้นls ../A/fooใช้งานได้

คุณแทนอาจพบว่ามีประโยชน์เพื่อให้สามารถcdไปจริง /tmp/Bไดเรกทอรีมากกว่า /tmp/A/Blinkaliased ในการทำเช่นนั้นคุณสามารถใช้ฟังก์ชันต่อไปนี้แทนcd(ซึ่งคุณสามารถใส่ใน. bashrc ของคุณ)

lcd() { cd $(readlink -f "$1"); }

lcdแน่นอนว่าใช้ได้กับทั้งไดเรกทอรีปกติและลิงก์สัญลักษณ์
หมายเหตุ: readlink -fทำหน้าที่ในเป้าหมายสุดท้ายของลิงก์ (เมื่อลิงก์ถูกเชื่อมโยงกับเดซี่)


1
cd -Pดูเหมือนง่ายขึ้น
jw013

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