如何讓 realpath 永遠不會解析符號連結?
我正在尋找一個命令來返回文件的絕對路徑,而不解析符號連結。一般來說,
realpath
這樣做很好。$ mkdir /tmp/test; cd /tmp/test $ mkdir foo $ ln -s foo bar $ realpath -se bar # good, this does not resolve the symlink /tmp/test/bar
它也適用於符號連結目錄中的文件。
$ touch foo/file $ realpath -se bar/file # good, this does not resolve the symlink /tmp/test/bar/file
但是,噹噹前導向器是符號連結目錄時,它會失敗
$ cd bar $ pwd /tmp/test/bar $ realpath -se file # this fails, returning the target /tmp/test/foo/file $ realpath -se . # this also fails, returning the target /tmp/test/foo $ realpath -se /tmp/test/bar/file # yet this works /tmp/test/bar/file $ realpath -se /tmp/test/bar # and this works /tmp/test/bar
為什麼會有這樣
realpath
的行為?(這是一個錯誤嗎?)有沒有辦法realpath
永遠解決符號連結,或者我應該使用另一種方法嗎?
程序的目前工作目錄 (CWD) 在作業系統級別從前一個程序繼承,或者可以使用
chdir(2)
. 作業系統(這裡我的意思是“核心”)當然總是會解析任何符號連結以確定最終結果必須是一個目錄,而不是一個符號連結(到一個目錄)。例如,之前的系統呼叫 ( ) 可以在有太多符號連結需要解析時chdir(2)
返回錯誤。ELOOP
因此,從作業系統的角度來看,CWD 不可能不是任何程序的目錄:作業系統將始終將其解析為真實路徑,而無需任何符號連結。一旦 shell 完成
cd /tmp/test/bar
,作業系統將 CWD 路徑解析為/tmp/test/foo
. 例如,在 Linux 系統上,ls -l /proc/$$/cwd
將顯示核心所見的已解析路徑的連結:/tmp/test/foo
.shell 仍然顯示
bar
在其提示符中的事實是因為它記住了之前完成的cd命令。行為可能取決於外殼類型。我會在這裡假設 bash 。所以它的內置pwd
(但不是外部/bin/pwd
命令)、$PWD
變數及其在中的使用$PS1
將對使用者“撒謊”關於目前目錄。任何程序,例如
realpath
,或/bin/pwd
從 shell 執行當然都會繼承實際的CWD,即/tmp/test/foo
. 所以這不是一個錯誤realpath
,它永遠不會有關於bar
.正如 Kusalananda 所建議的那樣,一種可能的尷尬方式是以某種方式重用
$PWD
變數並將其添加到realpath
’s 的論點,前提是它的論點已經不是絕對的。這是一個例子。我不確定有沒有辦法濫用它。例如,雖然下面的函式可以處理,
$PWD
但如果路徑中有換行符,變數本身在 bash 4.4.12 (Debian 9) 中表現不佳,但在 bash 5.0.3 (Debian 10) 中可以正常工作。當某處有換行符時,為了有用,-z
還應該添加一個選項,realpath
但我不會在這個簡單的範例中重新實現選項的整個解析。myrealpathnofollowsym () { for p in "$@"; do if ! printf '%s' "$p" | grep -q -- '^/'; then realpath -se "$PWD/$p" else realpath -se "$p" fi done }