Bash 在shell脚本中查找shell可执行文件目录的独立于平台的方法是什么?
根据POSIX: 在某些情况下,这并不明显。例如:Bash 在shell脚本中查找shell可执行文件目录的独立于平台的方法是什么?,bash,shell,cross-platform,posix,sh,Bash,Shell,Cross Platform,Posix,Sh,根据POSIX: 在某些情况下,这并不明显。例如: If the file is not in the current working directory, the implementation may perform a search for an executable file using the value of PATH, as described in Command Search and Execution. 我的Bash4.x没有遵循这个可选规则(出于安全考虑),所以我无法测试
If the file is not in the current working directory,
the implementation may perform a search for an executable
file using the value of PATH, as described in Command Search and Execution.
我的Bash4.x没有遵循这个可选规则(出于安全考虑),所以我无法测试它在现实生活中的表现
在shell脚本中查找shell可执行文件目录的独立于平台的方法是什么
PS。还有dirname$0
case失败原因:
#!/bin/sh
echo $0
dirname $0
当您:
$ sh runme.sh
runme.sh
.
所以你需要一些类似的东西:
CMDPATH=`cd $(dirname $0); echo $PWD`
为了使代码仅依赖于内置的shell功能,我将代码重写为:
PREVPWD=$PWD
cd ${0%${0##*/}}.
CMDPATH=$PWD
cd $PREVPWD
这看起来很难看,但不需要任何可执行文件…我相信您可以使用
EDIT3: 虽然严格来说POSIX还不是POSIX,但它自2012年以来一直是GNU核心应用程序。完全披露:在我在
info coreutils
TOC中注意到它之前,我从未听说过它,并立即想到了这个问题,但使用下面演示的功能应该是可靠的,(很快就会成功了?),我希望是有效的
为其调用者提供绝对来源的$0
:
% _abs_0() {
> o1="${1%%/*}"; ${o1:="${1}"}; ${o1:=`realpath -s "${1}"`}; eval "$1=\${o1}";
> }
% _abs_0 ${abs0:="${0}"} ; printf %s\\n "${abs0}"
/no/more/dots/in/your/path2.sh
EDIT4:值得强调的是,此解决方案在尝试扩展和解析路径之前,首先检查路径是否确实需要扩展和解析。这应该通过messenger变量返回绝对来源的$0
(值得注意的例外是-s
将保留符号链接
),就像我可以想象的那样,无论路径是否已经是绝对的
EDIT2:
现在我相信我更了解你的问题了,不幸的是,这使得下面的大部分内容变得无关紧要
(minor edit:在文档中找到realpath
之前,我至少减少了我的版本,以不依赖于时间域,但是,公平警告,在测试了一些之后,我不太相信ps
的命令路径扩展能力是完全可靠的)
另一方面,您可以这样做:
ps ww -fp $$ | grep -Eo '/[^:]*'"${0#*/}"
eval "abs0=${`ps ww -fp $$ | grep -Eo ' /'`#?}"
我需要修正它,以便更好地处理字段,而不是期望时间字段正好出现在流程路径之前,并依赖其包含的冒号作为引用,特别是因为这不会处理流程路径中的冒号,但我认为这很简单,很快就会发生。我相信该功能在其他方面与POSIX兼容。我认为,也许仅仅参数扩展就可以完成必要的工作
不严格相关(或正确):
这应适用于符合POSIX指南的所有情况:
echo ${0%/*}
编辑:
所以我承认,至少乍一看,我并不完全理解你所描述的问题。显然,在您的问题中,您对POSIX通过参数扩展进行变量字符串操作的标准有一定的了解(即使您的特定实现乍一看似乎有点紧张),因此我在解释您的问题时可能遗漏了一些重要的信息,至少在目前的形式下,这不是你想要的答案
我之前已经发布了内联变量null/set测试的参数扩展,正如您在“”问题中看到的那样,这些测试可能对您有用,也可能对您不有用。我之所以提到这一点,主要是因为我的答案在很大程度上是从POSIX参数扩展指南中复制/粘贴而来的,其中包括关于这个主题的指南覆盖范围,以及来自规范文档和我自己可能不太熟练的演示结构的一些示例
然而,我要坦率地承认,虽然我还没有完全理解你的问题,但我不相信你会在那里找到具体的答案。相反,我怀疑您可能已经忘记了,就像我偶尔忘记的那样,POSIX字符串操作中的#
和%
运算符用于指定要删除的字符串部分,而不是您希望保留的部分,因为有些人可能会觉得更直观。我的意思是,以这种方式搜索的任何字符串片段都被设计为从输出中消失,在删除指定的搜索字符串后,它将仅是原始字符串的剩余部分
这里有一点概述:
然而任何一个操作符的单个实例只会删除尽可能少的,以完全满足您的搜索,但是当双实例时,搜索将以贪婪的形式调用,删除您的搜索可能允许的原始字符串
除此之外,您只需知道一些基本正则表达式,并记住#
从左侧开始搜索删除字符串,然后向右扫描,而%
从右侧开始搜索,然后向左扫描
## short example before better learning if I'm on the right track
## demonstrating path manipulation with '#' and '%'
% _path_one='/one/two/three/four.five'
% _path_two='./four.five'
## short searching from the right with our wildcard to the right
## side of a single character removes everything to the right of
## of the specified character and the character itself
## this is a very simple means of stripping extensions and paths
% echo ${_path_one%.*} ${_path_one%/*}
/one/two/three/four /one/two/three
## long searching from the left with the wildcard to the left of
## course produces opposite results
% echo ${_path_one##*.} ${_path_one##*/}
five four.five
## will soon come back to show more probably
啊,我明白了,我在我的OSX上说readlink,并认为它无处不在。不,
意味着它工作完美:这是一个有效的相对路径名。如果在它前面添加$PWD,它将成为一个有效的非规范绝对路径名:/home/me/
一个更复杂但仍然正确的示例:/home/me/project1/../../../../opt/freeware/bin
您真正的问题似乎是“如何将路径名转换为绝对的规范形式?”@kubanczyk大多数问题来自POSIXsh
中$0
的定义。请参阅标题和正文。为什么您认为您的bash
没有执行PATH
查找?“可能”指的是命令可能是shell内置或函数。请阅读您的报价链接到的解析过程。@chepner,因为我的测试显示:cd/tmp;sh ls
-失败,原因是sh:0:无法打开ls
。@chepner:Trycd/tmp
## short example before better learning if I'm on the right track
## demonstrating path manipulation with '#' and '%'
% _path_one='/one/two/three/four.five'
% _path_two='./four.five'
## short searching from the right with our wildcard to the right
## side of a single character removes everything to the right of
## of the specified character and the character itself
## this is a very simple means of stripping extensions and paths
% echo ${_path_one%.*} ${_path_one%/*}
/one/two/three/four /one/two/three
## long searching from the left with the wildcard to the left of
## course produces opposite results
% echo ${_path_one##*.} ${_path_one##*/}
five four.five
## will soon come back to show more probably