1

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 上.)

4

2 回答 2

2

即使是当前版本的 OSX (10.11.3) 也没有附带realpath实用程序,因此您的实用程序必须确实来自 GNU coreutilsHomebrew 包。

事实上,你可以很容易地用realpath它自己来验证;例如:

$ realpath "$(which realpath)"
/usr/local/Cellar/coreutils/8.24/bin/grealpath

Bujiraso 的有用答案中,使用--relative-base="$HOME"并简单地添加是您情况下最简单的解决方案。~/

让我提出一个替代方案:

  • 不用realpath,因为它的存在不能假设在 OSX 机器上。

    • 而是使用 Perl 单线(Python 也是一种选择)。
  • 使用$HOME而不是~,因为基于路径$HOME更安全的选择(假设shell扩展了路径):

    • $HOME更安全,因为它允许将整个路径字符串在传递给 shell 时被双引号括起来,而不必担心单独引用(转义)嵌入的空格和其他 shell 元字符;相比之下,使用~-prefixed 路径,您要么必须引用路径中的单个字符,要么有选择地将~/前缀不加引号( ~/"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重击功能:

# 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
}
于 2016-02-27T20:37:34.537 回答
1

realpath本身似乎没有这个功能,但是一个简单的解决方案可能是回显波浪号+斜线本身的前缀,然后是相对的真实路径。也就是说,您可以使用 relative-base 和 echo 的组合,而不是 sed。例如:

[user@localhost ~]$ echo "~/$(realpath --relative-base=$HOME bin/myScript)"
~/bin/myScript 
于 2016-02-27T19:18:23.190 回答