realpath
非常好用,它为您提供了一种简单的方法来获取文件的真实路径,但我无法找到满足我需求的方法(不进行自己的字符串操作,并且因此可能会错过专用实用程序可能已找到并解决的极端情况)。简而言之,我希望在它返回的路径中包含~
,因此它可以跨机器有效。
因此,如果我在~/bin
并输入realpath --some-option script.sh
,我希望它返回~/bin/script.sh
而不是bin/script.sh
,如果我使用的选项,这就是我得到的是--relative-base=$HOME
,而不是/Users/brandon/bin/script.sh
,如果我不使用任何选项,这就是我得到的。
有没有办法从realpath
获得我想要的东西,还是有其他一些实用程序以简单的方式完成我想要的工作?或者只是通过sed
来获取我想要的东西的唯一真正选择?
(PS我在OS X上,但我已经安装了GNU实用程序,以防需要...我不确定这是realpath
来自哪里,或者现在是否安装了在更新版本的OS X上默认使用。)
答案 0 :(得分:1)
realpath
本身似乎没有这个功能,但是一个简单的解决方案可能是回显tilde +斜杠本身的前缀,然后是相对的实际路径。也就是说,你可以使用相对基数和回声的组合,而不是sed。
例如:
[user@localhost ~]$ echo "~/$(realpath --relative-base=$HOME bin/myScript)"
~/bin/myScript
答案 1 :(得分:1)
即使当前版本的OSX(10.11.3)不也带有realpath
实用程序,因此您的确必须来自GNU coreutils
Homebrew包。< / p>
事实上,您可以使用realpath
本身轻松验证; e.g:
$ realpath "$(which realpath)"
/usr/local/Cellar/coreutils/8.24/bin/grealpath
使用--relative-base="$HOME"
并简单地预先~/
,就像在Bujiraso's helpful answer中一样,是您案例中最简单的解决方案。
让我提出一个替代方案:
不使用realpath
,因为无法在OSX计算机上假设其存在。
使用$HOME
代替~
,因为基于$HOME
的路径是更安全的选项(假设 shell 扩展路径):
$HOME
更安全,因为它允许整个路径字符串在传递给shell时被双引号,而不必担心单独引用(转义)嵌入空格和其他shell元字符;相比之下,使用~
- 前缀路径,您必须在路径中引用个别字符,或者选择性地保留~/
前缀不带引号(~/"path/..."
)。absPath=$(perl -MCwd -le 'print Cwd::abs_path(shift)' "script.sh")
abstractPath="\$HOME${absPath#"$HOME"}"
结果将类似于 literal $HOME/bin/script.sh
,当由shell解释时,它将扩展为当时用户特定的路径。
如果您定义下面打印的abstractHomePath()
bash
功能,您可以使用:
abstractPath=$(abstractHomePath "script.sh") # -> '$HOME/bin/script.sh'
abstractHomePath
Bash功能:
# Given a relative or absolute path, returns an absolute path in which the path
# prefix that is the current user's home directory is replaced with literal
# '$HOME' so as to yield an abstract path that can later be expanded in a
# different user's context to get the analogous path.
#
# If the input path resolves to an absolute path that is *not* prefixed with
# the current user's home diretory path, the absolute path is returned as -is.
#
# Note that any symlinks in the path are resolved to their ultimate targets
# first and that the path is normalized.
#
# Examples:
# abstractHomePath ~ # -> '$HOME'
# abstractHomePath /Users/jdoe/Downloads # -> '$HOME/Downloads'
# abstractHomePath /tmp # -> '/private/tmp' - symlink resolved, but no $HOME prefix
# Prerequisites:
# Requires Perl v5+
abstractHomePath() {
local absPath=$(perl -MCwd -le 'print Cwd::abs_path(shift)' "$1")
if [[ $absPath == "$HOME"* ]]; then
printf '%s\n' "\$HOME${absPath#"$HOME"}"
else
printf '%s\n' "$absPath"
fi
}