
我創建了帶有目錄絕對路徑的符號連結(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 ../foo
,ls
並不知道 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
作用於連結的最終目標(當連結是菊花鏈時)。