Symlink

“ln”和“ln -s”的看似不一致的行為

  • September 20, 2018

眾所周知,該ln命令創建一個連結,預設為硬連結,-s選項創建符號連結。一般語法是ln [-s] OLD NEW,其中 OLD 是您要連結的文件, NEW 是您正在創建的新文件。不能為目錄創建硬連結,因為可以在彼此內部的文件夾之間創建硬連結&我想電腦還沒有資源來檢查這個沒有嚴重的減速。

創建連結時,必須寫出兩個文件的路徑,可以是絕對的或相對的。您可以混合使用相對和絕對文件路徑,即新文件/文件夾的相對路徑和舊文件/文件夾的絕對路徑。使用相對路徑創建硬連結時,兩個文件的路徑都相對於目前文件夾,而對於符號連結,連結到的文件/文件夾的路徑相對於其父文件夾,但舊文件的路徑/folder 相對於目前文件夾。為什麼這與我的問題“相對”。

例如,假設我們在 HOME 文件夾中/home/user,也稱為~,並創建 2 個文件夾,new並且new2,與文件file夾中的文件new。如果我們嘗試,結果是與目前不存在ln -s new/file new2/file的連結斷開。但是,如果我們改為執行,我們會得到預期的結果,即來自to的連結。~/new2/file``~/new2/new/file``ln -s ../new/file new2/file``~/new2/file``~/new/file

所以,我的問題:

為什麼符號連結的 OLD 文件/文件夾的文件路徑是相對於其父級的,而其他 3 個路徑(硬連結 OLD、NEW 文件、符號連結 NEW 文件/文件夾)是相對於目前文件夾的?

所有這些都在 Fedora 上,但我確信它適用於大多數基於 UNIX 的作業系統。

編輯E Carter Young 似乎對我的第二個問題(以及我的第一個問題,無論如何都是錯誤的)一針見血。似乎對於符號連結,目標不必存在,因此系統必須使其路徑相對於連結而不是目前目錄。但是,為什麼在您執行命令時 shell 不能解析出該路徑,而不是強迫使用者弄清楚路徑是什麼並自己輸入?shell 似乎解析得很好,所以這是遺留問題的案例嗎?性能問題?什麼?

閱讀您的手冊頁:問題 1 = 1st Form,這是因為在 linux 中,所有項目都被視為文件,甚至是目錄。例如,使用您的文本編輯器“打開”/etc/,即: nano -w /etc/ nano 會禮貌地告訴您 /etc/ 是一個目錄,因為從技術上講,創建永無止境的符號連結是合法的。在過去,在編寫邊界檢查之前,我可以有一個 FHS 系統,其中有 2 個名為 /etc 的文件,一個是文件,一個是目錄,系統知道其中的區別

(請參閱chromiumos 開發人員指南中的哈哈說明:

有一個文件系統循環,因為在 ~/trunk 中你會再次找到 chroot。不要想這個太久。如果您嘗試使用 du -s ${HOME}/chromiumos/chroot/home,您可能會收到有關文件系統損壞的消息。這沒什麼好擔心的,只是意味著你的電腦也不理解這個循環。(如果你能理解這個循環,那就更努力一點。

我敢你,點擊更難的東西:) 為了防止循環 ln 需要完整路徑。

問題2可以通過再次閱讀man page來回答看最後一句:

描述

   In the 1st form, create a link to TARGET with the name LINK_NAME.  In
   the 2nd form, create a link to TARGET in the current directory.  In
   the 3rd and 4th forms, create links to each TARGET in DIRECTORY.
   Create hard links by default, symbolic links with --symbolic.  By
   default, each destination (name of new link) should not already
   exist.  When creating hard links, each TARGET must exist.  Symbolic
   links can hold arbitrary text; if later resolved, a relative link is
   interpreted in relation to its parent directory.

回复:編輯: “但是,為什麼在您執行命令時外殼不能解析出該路徑,而不是強迫使用者弄清楚路徑是什麼並自己輸入?”


考慮這個例子:應用程序 A 安裝庫版本 1.0.a。您建構依賴於庫 A 的應用程序 X、Y、Z。應用程序 A 發現錯誤,更新它並將庫保存為 1.0.1.2.a。由於應用程序 X、Y 和 Z 仍然使用庫 1.0,如果我直接用 1.0.1.2 替換 1.0,我會損壞,但如果我將版本 1.0.1.2 符號連結到版本 1.0,沒有任何問題,

ln -s /usr/lib64/libfoo-1.0.1.2.a /usr/lib64/libfoo-1.0.a

並且應用程序 X、Y 和 Z 也從應用到它們的庫中獲得了新的錯誤修復,因為 shell 遵循從 1.0 到 1.0.1.2 的連結,但將其稱為 1.0。在這種情況下,您不希望 shell 假定路徑,因為您增加了系統範圍內損壞的機會。順便說一句,64 位系統上的 /usr/lib 連結到 /usr/lib64,以糾正我剛剛給出的大規模範例,即 32 位應用程序希望庫安裝在 /usr/lib 和 64 位系統沒有純 32 位庫,因此 /usr/lib 連結到 /usr/lib64,如下所示:

ln -s /usr/lib64 /usr/lib

引用自:https://unix.stackexchange.com/questions/124962