目錄和相對路徑的符號鏈接

目錄和相對路徑的符號鏈接

我創建了帶有目錄絕對路徑的符號連結(Blink),並具有以下範例樹:

$ 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

內建 cd 指令根據需要解析路徑,但外部 ls 將 .. 視為 /tmp/B 的上層,因此無法找到 foo。

這裡有什麼問題?我可以透過相對路徑(如 ../foo)從 /tmp/A/Blink 取得 foo 檔案嗎?

答案1

shell 將目前工作目錄儲存在$PWD.這就是 shell 內建命令cd和的用途pwd,並且它將符號連結視為普通目錄,如您所見。有時這很有幫助,有時則沒有。

您可以使用以下方式找到真實目錄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

答案2

我不認為你能做到這一點。如今,Shell 會追蹤它們如何到達所在位置,它們按名稱追蹤當前工作目錄,而不僅僅是依賴檔案系統和作業系統來保存它。這意味著內建函數cd可以“備份”符號鏈接,而不是直接跟隨“..”鏈。

但是當您運行時ls ../fools並不知道 shell 透過符號連結到達了目錄。 將在“../foo”上ls執行操作。 stat()“..”部分來自目前目錄,其父目錄只有一個“..”條目。整個符號連結並沒有改變目錄具有單一“.”的方式。和一個“..”條目。符號連結允許核心在檔案路徑中插入額外的間接層。當您將“../whatever”傳遞給open()或 時stat(),核心僅使用執行呼叫的程序的當前工作目錄來確定哪個目錄以“..”命名。

答案3

Bruce 和 ams 給了漂亮的答案,解釋了背後的行為。但要真正做到ls ../foo你所要求的,你可以選擇類似的東西

ls $(dirname $PWD)/foo

答案4

你做不到,因為/tmp/A/Blink 實際上/tmp/B。所以,ls ../A/foo確實有效。

相反,您可能會發現能夠光碟真實的 /tmp/B目錄,而不是別名/tmp/A/Blink.為此,您可以使用以下函數代替cd(您可以將其放入 .bashrc 中)

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

lcd當然,適用於普通目錄和符號連結目錄。
注意:readlink -f作用於連結的最終目標(當連結是菊花鏈時)。

相關內容