Bash

在 zsh/Bash 中通配時部分解析/遵循符號連結

  • August 16, 2021

假設我有一個文件,該文件a是指向 的符號連結b,而該文件又是指向 的符號連結c

使用 zsh 的:A修飾符,通配 a 將產生一個絕對路徑,解析所有符號連結,因此a(:A)將擴展為c(在具有該realpath庫的系統上)的絕對路徑。

是否有可能獲得b(絕對的或相對的,但直接作為萬用字元的結果,而不是例如通過查看 的輸出ls -l)甚至是任意符號連結深度的文件?

Bash 的解決方案也很有趣。

您始終可以創建一個與+glob 限定符一起使用的函式:

$ zmodload zsh / 統計
$ resolve() { [[ -L $REPLY ]] && stat -A REPLY +link -- ${1-$REPLY}; }
$ print -r -a(+resolve)
b
$ print -r - a(+resolve:a)
/home/stephane/b (儘管請參閱下面的警告)

請注意,如果您這樣做a(+resolve+resolve),第二個resolve仍將在原始文件名 ( a) 上呼叫,而不是在第一個resolve( b) 的結果上呼叫。但是,您可以這樣做:

$ print -r - a(e['resolve && resolve'])
c

將兩個resolves 連結起來。然而(並且警告也適用於:a上面的用法),雖然它適用於這個特定的例子,但在一般情況下這不是一個有效的事情,因為符號連結的目標,當相對路徑相對於父級時符號連結,而不是目前工作目錄,所以如果dir/link指向foo,那是dir/foo文件,而不是foo,所以它僅在解析目前工作目錄中的符號連結時有效。

這將不再是一個問題,但如果我們改變我們的resolveso 它計算符號連結目標的完整路徑:

resolve() {
 local target
 [[ -L $REPLY ]] &&
   stat -A target +link -- ${1-$REPLY} &&
   case $target in
     (/*) REPLY=$target;;
     (*) REPLY=${REPLY:h:a}/$target;;
   esac
}

bash沒有 glob 限定符,也沒有任何介面readlink()(如zsh’sstat內置),但在某些系統上,您會找到一個readlink命令:

$ readlink a
b

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