Bash 在shell脚本中查找shell可执行文件目录的独立于平台的方法是什么?

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没有遵循这个可选规则(出于安全考虑),所以我无法测试

根据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没有遵循这个可选规则(出于安全考虑),所以我无法测试它在现实生活中的表现

在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大多数问题来自POSIX
sh
$0
的定义。请参阅标题和正文。为什么您认为您的
bash
没有执行
PATH
查找?“可能”指的是命令可能是shell内置或函数。请阅读您的报价链接到的解析过程。@chepner,因为我的测试显示:
cd/tmp;sh ls
-失败,原因是
sh:0:无法打开ls
。@chepner:Try
cd/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