这个问题在这里已有答案:
我有一个Bash脚本需要知道它的完整路径 . 我试图找到一种广泛兼容的方式来做到这一点,而不会结束相对或时髦的路径 . 我只需要支持Bash,而不是sh,csh等 .
到目前为止我发现了什么:
-
Getting the source directory of a Bash script from within地址的接受答案是通过
dirname $0
获取脚本的路径,这很好,但是可能会返回相对路径(如.
),如果要更改脚本中的目录并使路径保持不变,这是一个问题指向脚本的目录 . 尽管如此,dirname
将成为这个难题的一部分 . -
Bash script absolute path with OS X的已接受答案(特定于OS X,但答案无论如何都有效)会给出一个函数,该函数将测试
$0
是否看起来相对,如果是,则会将$PWD
预先挂起 . 但结果仍然可以有相对位(虽然总体来说它是绝对的) - 例如,如果脚本是/usr/bin
目录中的t
并且你在/usr
并且你键入bin/../bin/t
来运行它(是的,这是复杂的),你以/usr/bin/../bin
结尾作为脚本的目录路径 . 哪个 works ,但...... -
readlink
解决方案on this page,如下所示:
# Absolute path to this script. /home/user/bin/foo.sh
SCRIPT=$(readlink -f $0)
# Absolute path this script is in. /home/user/bin
SCRIPTPATH=`dirname $SCRIPT`
但 readlink
isn 't POSIX and apparently the solution relies on GNU' s readlink
其中BSD 's won' t由于某种原因起作用(我无法访问类似BSD的系统进行检查) .
所以,各种方式,但他们都有他们的警告 .
什么是更好的方式? “更好”的意思是:
-
给了我绝对的道路 .
-
即使以复杂的方式调用,也要取出时髦的位(参见上面#2的评论) . (例如,至少适度规范化路径 . )
-
仅依赖于Bash-isms或几乎肯定会出现在最流行的* nix系统(GNU / Linux,BSD和类似BSD的系统,如OS X等)上的东西 .
-
如果可能,避免调用外部程序(例如,更喜欢Bash内置程序) .
-
( Updated ,谢谢你抬起头来,wich)它并不喜欢让它们独自一人,但这并不是必须的 .
23 回答
这里's what I'提出了(编辑:加上sfstewman,levigroker,Kyle Strand和Rob Kennedy提供的一些调整),这似乎最符合我的"better"标准:
那条
SCRIPTPATH
线似乎特别迂回,但我们需要它而不是SCRIPTPATH=
pwd`` 才能正确处理空格和符号链接 .还要注意,深奥的情况,例如执行一个完全不可能来自可访问文件系统中的文件的脚本(这是完全可能的),不能满足那里(或者我见过的任何其他答案) ) .
我很惊讶这里没有提到
realpath
命令 . 我的理解是它广泛便携/移植 .您的初始解决方案变为
并根据您的偏好保留未解析的符号链接:
我发现在Bash中获得完整规范路径的最简单方法是使用
cd
和pwd
:无论脚本是作为
<name>
还是source <name>
调用,使用${BASH_SOURCE[0]}
而不是$0
都会产生相同的行为 .我今天不得不重新审视这个问题并找到Getting the source directory of a Bash script from within . 它详细阐述了I've used in the past as well的解决方案 .
链接答案中有更多变体,例如:对于脚本本身是符号链接的情况 .
再次考虑这个问题:这个线程中引用了一个非常流行的解决方案,其原点是here:
由于使用了dirname,我远离了这个解决方案 - 它可能会带来跨平台的困难,特别是如果出于安全原因需要锁定脚本 . 但作为一个纯粹的Bash替代品,如何使用:
这是一个选择吗?
获取shell脚本的绝对路径
它不使用readlink中的
-f
选项,因此它应该适用于BSD / Mac OS X.支持
source ./script(由
.
点运算符调用时)绝对路径/路径/到/脚本
相对路径,如./script
/path/dir1/../dir2/dir3/../script
从符号链接调用时
当嵌套符号链接时,例如
foo->dir1/dir2/bar bar->./../doe doe->script
当调用者更改脚本名称时
I am looking for corner cases where this code does not work . 请告诉我 .
代码
已知的问题
该脚本必须位于某个磁盘上 . 让它通过网络 . 如果您尝试从PIPE运行此脚本,它将无法正常工作
从技术上讲,它是未定义的 . 实际上,没有理智的方法来检测这一点 . (协同进程无法访问父进程的环境 . )
使用:
which
将标准输出打印到可执行文件的完整路径在shell提示符下输入传递的参数时执行(这是$ 0包含的内容)dirname
从文件名中删除非目录后缀 .因此,无论路径是否被指定,您最终都会获得脚本的完整路径 .
由于我的Linux系统上没有默认安装realpath,以下内容适用于我:
$SCRIPT
将包含脚本的实际文件路径,$SCRIPTPATH
包含脚本的目录的实际路径 .在使用之前阅读this answer的评论 .
很晚才回答这个问题,但我使用:
我们已将自己的产品realpath-lib放置在GitHub上,以供免费和无阻碍的社区使用 .
无耻的插件,但有了这个Bash库你可以:
这个函数是库的核心:
它不需要任何外部依赖,只需要Bash 4 . 还包含
get_dirname
,get_filename
,get_stemname
和validate_pathvalidate_realpath
的函数 . 它是免费的,干净的,简单的,文档齐全的,因此它也可以用于学习目的,毫无疑问可以改进 . 跨平台尝试 .更新:经过一些审查和测试后,我们用一些实现相同结果的东西替换了上面的函数(不使用dirname,只有纯Bash),但效率更高:
这还包括一个环境设置
no_symlinks
,它提供了解析物理系统符号链接的功能 . 默认情况下,它保持符号链接不变 .Bourne shell(
sh
)符合方式:您可以尝试定义以下变量:
或者您可以在Bash中尝试以下功能:
这个函数有一个参数 . 如果参数已经有绝对路径,则按原样打印,否则打印$ PWD变量filename参数(不带./前缀) .
有关:
Bash script absolute path with OS X
Getting the source directory of a Bash script from within
只是:
不需要花哨的操作员 .
易于阅读?以下是另一种选择 . 它忽略了符号链接
接受的解决方案不方便(对我来说)不是"source-able":
如果你从“
source ../../yourScript
”调用它,$0
将是“bash
”!以下函数(对于bash> = 3.0)为我提供了正确的路径,但是可以调用脚本(直接或通过
source
,具有绝对路径或相对路径):("right path",我的意思是 full absolute path of the script being called ,即使从另一条路径调用,直接或用“
source
”)关键是要检测“
source
”情况并使用${BASH_SOURCE[0]}
来取回实际的脚本 .也许接受以下问题的答案可能会有所帮助 .
How can I get the behavior of GNU's readlink -f on a Mac?
鉴于你只想规范化连接$ PWD和$ 0得到的名称(假设$ 0不是绝对的开头),只需沿着
abs_dir=${abs_dir//\/.\//\/}
等行使用一系列正则表达式替换 .是的,我知道它看起来很可怕,但它会起作用并且是纯粹的Bash .
如果我们使用Bash,我相信这是最方便的方式,因为它不需要调用任何外部命令:
试试这个:
一个班轮
只是为了它的地狱我已经做了一些黑客攻击一个纯文本的东西,纯粹在Bash . 我希望我能 grab 所有边缘案例 .
请注意,我在另一个答案中提到的
${var//pat/repl}
并没有使它仅替换最短的匹配,这是替换/foo/../
的问题,例如,/*/../
将采取之前的一切,而不仅仅是一个条目 . 而且由于这些模式不是如何才能发挥作用 . 所以这是我提出的非常复杂的解决方案,享受 . ;)顺便提一下,如果您发现任何未处理的边缘情况,请告诉我 .
我已成功使用以下方法一段时间(虽然不是在OS X上),它只使用内置的shell并处理'source foobar.sh'的情况,就我所见 .
一个问题(匆匆放在一起)的例子下面的代码是函数使用$ PWD,它在函数调用时可能正确也可能不正确 . 所以这需要处理 .
还有另一种方法:
更简单的说,这对我有用: