从脚本中找到绝对路径


10

在脚本中,我进入$0了可能的相对路径。为了将其转换为绝对值,我发现了我不理解的解决方案:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

我的问题是内部的魔法${0%/*}${0##*/}。看起来前者提取目录名,而后者提取文件名,我只是不知道如何。


2
那使用了参数扩展,但是对我没有用。如果您的脚本仅在Linux上使用,则可以使用readlink -f $0来获取规范路径。
肖恩·高夫

1
@Shawn:1个非常好的评论表决,因为您引入了正确的思想:“这使用了参数扩展,但对我不起作用”。该dirname实用程序在这里很有用。
D4RIO 2011年

mywiki.wooledge.org/BashFAQ/028cyberciti.biz/faq/…BASH_SOURCE的要好于$0,因为可以$0输入用户键入的命令,而该命令可能不是当前正在执行的脚本。
Joel Purra 2014年

Answers:


8

定义:

${string%substring}$substring从的末尾 删除最短匹配$string

${string##substring}$substring从的开头删除最长匹配项$string

你的例子:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

${0%/*} 删除最后一个斜杠之后的所有内容,为您提供脚本的目录名称(可能是相对路径)。

${0##*/} 删除最后一个斜杠之前的所有内容,仅提供脚本名称。

因此,此命令将更改为脚本的目录,并将当前的工作目录(由提供给$PWD)和脚本名称连接起来,从而为您提供绝对路径。

要查看发生了什么,请尝试:

echo ${0%/*}
echo ${0##*/}

在所有变量扩展名周围添加双引号,以应对(几乎所有)包含shell特殊字符的文件名。
吉尔斯(Gilles)“所以,别再邪恶了”,

10

肖恩拥有最简单的解决方案:readlink -f $0。如果要绝对确定要处理奇怪的文件名,可以使用以下命令:

absolute_path_x="$(readlink -fn -- "$0"; echo x)"
absolute_path="${absolute_path_x%x}"

文献资料


1
很高兴看到最终换行符得到正确处理。不幸的readlink -fn是特定于Linux,NetBSD和OpenBSD。
吉尔(Gilles)“所以,别再邪恶了”,

4

这是执行此工作的更安全,更易读的方法:

abspath=$(unset CDPATH && cd "$(dirname "$0")" && echo $PWD/$(basename "$0"))

笔记:

  • 如果$0是没有前路径的裸文件名,则原始脚本将失败,但此处给出的脚本将起作用。(这不是问题,$0但可能在其他应用程序中。)
  • 如果文件路径实际上不存在,则任何一种方法都将失败。(,这不是问题$0,但可能在其他应用程序中也是如此。)
  • unset如果您的用户可能已CDPATH设置,则必不可少。
  • 不同于readlink -frealpath,这将适用于非Linux版本的Unix(例如Mac OS X)。

2

如果您想学习Shell参数扩展,可以从这里开始阅读,但是扩展并不总是一个好的选择。在这种情况下,几乎每个类似Unix的系统都有2个良好的utils:

basename
dirname

第一个将提取文件名,而第二个将提取路径,因此,如果您有$ 0,请说:

dirname $0

这样您就可以走。

干杯


dirname可以返回相对路径
opticyclic

0

引入bw内置的pwd。也可以在GNU coreutils包中找到。

$ sh ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
$0: ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
cheeky binary from /home/jaroslav/tmp (/home/jaroslav/tmp)

$ cat /home/jaroslav/tmp/somewhere.sh

abs=$( cd `dirname "$0"` ; pwd -P)
absBin=$( cd `dirname "$0"` ; /bin/pwd -P)
echo \$0: $0
echo cheeky binary from $abs \($absBin\)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.