Fyl*_*lke 7 shell bash symlink
我想测试一个相对符号链接是否指向某个目录的子树。
这个例子会产生,false因为它指向foo目录之外:
/foo>readlink bar
../fie.txt
虽然这个例子会产生true:
/foo>readlink bar
fum/fie.txt
是否有我可以利用的现有实用程序,或者我必须从头开始编写代码?我正在使用bash.
我不认为有这样的实用程序。使用 GNU readlink,您可以执行以下操作:
is_in() (
needle=$(readlink -ve -- "$1" && echo .) || exit
haystack=$(readlink -ve -- "$2" && echo .) || exit
needle=${needle%??} haystack=${haystack%??}
haystack=${haystack%/} needle=${needle%/}
case $needle in
("$haystack" | "$haystack"/*) true;;
(*) false;;
esac
)
Run Code Online (Sandbox Code Playgroud)
这解决了所有符号链接,最终得到了针和干草堆的规范绝对路径。
我们得到了双方的规范化绝对路径针和干草堆。我们使用-e而不是-f因为我们想确保文件存在。-v如果无法访问文件,该选项会给出错误消息。
与往常一样,--应该用于标记选项和引用的结束,因为我们不想在此处调用 split+glob 运算符。
类似 Bourne 的 shell 中的命令替换有一个缺陷,它会从命令输出的末尾删除所有换行符,而不仅仅是命令添加到最后一行的换行符。这意味着对于像/foo<LF><LF>,$(readlink -ve -- "$1")会返回/foo. 常见的解决方法是附加一个非 LF 字符(此处.)并删除该字符以及由readlinkwith添加的额外 LF 字符var=${var%??}(删除最后两个字符)。
如果针是干草堆或干草堆/某物,则将针视为在干草堆中。但是,如果干草堆是/(/etc例如不是//something),那将不起作用。/经常需要特别对待,因为虽然/和/xx斜线数量相同,但一个比另一个高一个级别。
解决它的一种方法是用/完成的空字符串替换var=${var%/}(唯一以/该结尾的路径readlink -e可能输出是/,因此删除尾随/更改/为空字符串)。
对于文件路径的规范化,您可以使用辅助函数。
canonicalize_path() {
# canonicalize paths stored in supplied variables. `/` is returned as
# the empty string.
for _var do
eval '
'"$_var"'=$(readlink -ve -- "${'"$_var"'}" && echo .) &&
'"$_var"'=${'"$_var"'%??} &&
'"$_var"'=${'"$_var"'%/}' || return
done
}
is_in() (
needle=$1 haystack=$2
canonicalize_path needle haystack || exit
case $needle in
("$haystack" | "$haystack"/*) true;;
(*) false;;
esac
)
Run Code Online (Sandbox Code Playgroud)