liên kết tượng trưng đến một thư mục và đường dẫn tương đối


15

Tôi đã tạo symlink với đường dẫn tuyệt đối đến thư mục (Blink) và có ví dụ như cây sau:

$ 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

sau đó tôi đi đến / tmp / A và thay đổi thư mục thành Blink:

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

cd ..trả lại cho tôi /tmp/A nhưng nếu tôi gõ ví dụ ls ../footôi sẽ gặp lỗi:

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

Lệnh cd dựng sẵn giải quyết đường dẫn khi cần, nhưng ls bên ngoài coi .. là mức tăng của / tmp / B và do đó không thể tìm thấy foo.

vấn đề ở đây là gì? Tôi có thể lấy tệp foo từ / tmp / A / Blink bằng đường dẫn tương đối như ../foo không?


Câu hỏi tương tự được đăng chéo trên SuperUser
Peter.O

Câu trả lời:


13

Tôi không nghĩ bạn có thể làm điều này. Shell hiện nay theo dõi cách họ có được vị trí của họ, họ theo dõi thư mục làm việc hiện tại theo tên, thay vì chỉ dựa vào hệ thống tệp và hệ điều hành để giữ nó. Điều đó có nghĩa là tích hợp cdcó thể "sao lưu" liên kết tượng trưng, ​​thay vì chỉ theo chuỗi ".." trực tiếp.

Nhưng khi bạn chạy ls ../foo, lskhông biết rằng shell đã vào một thư mục bằng cách theo các liên kết tượng trưng. lssẽ làm một stat()"../foo". Phần ".." xuất phát từ thư mục hiện tại, chỉ có một mục ".." duy nhất cho phụ huynh. Toàn bộ điều liên kết tượng trưng không thay đổi cách các thư mục có một "." và một mục ".." duy nhất. Các liên kết tượng trưng cho phép kernel chèn thêm một lớp cảm ứng vào đường dẫn tệp. Khi bạn chuyển "../whthing" cho open()hoặc stat(), kernel chỉ sử dụng thư mục làm việc hiện tại của quá trình thực hiện lệnh gọi để tìm ra thư mục đơn nào được đặt tên theo "..".


17

Shell lưu trữ thư mục làm việc hiện tại trong $PWD. Đó là những gì được sử dụng cho các nội trang shell cdpwd, và nó coi các liên kết tượng trưng như các thư mục bình thường, như bạn đã thấy. Đôi khi điều này là hữu ích, đôi khi không.

Bạn có thể tìm thấy thư mục thực bằng cách sử dụng pwd(gõ help pwdđể biết thêm chi tiết):

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

Tương tự, cdcó một tùy chọn -P(một lần nữa, help cdlà bạn của bạn):

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

Cuối cùng, bạn có thể tắt "tính năng" hoàn toàn:

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

Cảm ơn, tôi biết về tính năng set -P, nhưng bị nhầm lẫn bởi hành vi lệnh ls ...
user478681

Như tôi đã nói, set -Phành vi sử dụng và ls bắt đầu có ý nghĩa. :)
AMS

2

Bruce và ams đã đưa ra những câu trả lời đẹp giải thích cho hành vi đằng sau. Nhưng để thực sự làm những ls ../foogì bạn yêu cầu, bạn có thể đi với một cái gì đó như

ls $(dirname $PWD)/foo

1

Bạn không thể làm điều đó, vì /tmp/A/Blink thực sự /tmp/B. Vì vậy, ls ../A/fookhông làm việc.

Thay vào đó, bạn có thể thấy hữu ích khi có thể cd vào thư mục thực /tmp/B , thay vì bí danh /tmp/A/Blink. Để làm điều đó, bạn có thể sử dụng hàm sau thay vì cd(mà bạn có thể đặt vào .bashrc của mình)

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

lcd, tất nhiên, hoạt động cho cả hai thư mục bình thường và liên kết tượng trưng.
Lưu ý: readlink -fhành động trên mục tiêu cuối cùng của liên kết (khi các liên kết được nối xích) ..


1
cd -Pcó vẻ đơn giản hơn
tháng 3/2013

@ jw013: Bạn nói đúng; nó là. Tôi đã không nhận ra điều đó .. cảm ơn ..
Peter.O
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.