shell脚本可以告诉它所使用的目录吗';她进来了。没有巴什主义

shell脚本可以告诉它所使用的目录吗';她进来了。没有巴什主义,shell,sh,Shell,Sh,受到这个问题的启发 这是可能的,但不需要bash 我正在运行Ubuntu,在我需要Bash问题的公认解决方案之前,我的哈希爆炸是这样的 #!/bin/sh 我喜欢这样,有没有办法保持这样 编辑: 它应该输出正确的目录,即使这样运行 ./script.sh $(dirname--“$0”)怎么样 如果您的shell仅使用反勾号,则它将是: `dirname -- "$0"` 无需创建额外的进程并调用dirname。在shell提示符中直接运行程序时(例如$0==“-bash”),或者通过搜

受到这个问题的启发

这是可能的,但不需要bash

我正在运行Ubuntu,在我需要Bash问题的公认解决方案之前,我的哈希爆炸是这样的

#!/bin/sh
我喜欢这样,有没有办法保持这样

编辑:

它应该输出正确的目录,即使这样运行

./script.sh
$(dirname--“$0”)
怎么样

如果您的shell仅使用反勾号,则它将是:

`dirname -- "$0"`
无需创建额外的进程并调用
dirname
。在shell提示符中直接运行程序时(例如$0==“-bash”),或者通过搜索$PATH调用程序时,可能会发生位置不确定的情况。(那么$0也将不带斜杠)


如果不对其运行的系统进行假设,就不可能以可靠的方式执行此操作。这涉及到很多关于这个问题的细节

该页面提供了以下备选方案:

将脚本的配置保存在 单个静态位置,如/etc/foobar.conf。如果你需要 定义多个配置文件,然后就可以有一个目录 (比如说,/var/lib/foobar/或/usr/local/lib/foobar/),然后读一读 目录在固定位置的位置,如/etc/foobar.conf。如果 你甚至不想那么多被硬编码,你可以通过考试 foobar.conf(或配置目录本身)的位置 脚本的参数。如果您需要脚本来假定 默认值如果没有/etc/foobar.conf,可以在 脚本本身,或者返回到类似$HOME/.foobar.conf的内容 如果缺少/etc/foobar.conf。当您将脚本安装到 在目标系统中,可以将脚本的位置放入 剧本本身。该信息在该点可用,如图所示 只要脚本不移动,它将始终保持正确 每个已安装的系统。在大多数情况下,中止更有意义 如果您的配置数据无法通过明显的方式找到, 而不是经历神秘的过程,可能会想出 错误的答案

就我个人而言,我使用:

EXEC_DIR=$( readlink -f $( dirname -- "$0" ) )

在我的shell脚本(/bin/sh)中。到目前为止,对我来说还行。

/bin/sh
是一个与伯恩兼容的shell(今天是
bash
ksh
)。在这些脚本上,以下代码行将为您提供当前运行脚本的绝对路径:

DIR=$( cd $( dirname -- "$0" ) > /dev/null ; pwd )
这一行有很多智慧:

  • 引号确保路径中的空格不会导致问题
  • 不需要引号来保护
    $(…)
    的结果。如果使用反勾号,则需要更多的引号,但由于反勾号存在许多问题,现在几乎所有shell都支持
    $()
  • $()
    有一个很好的副作用,即命令在子shell中执行,因此当前路径不会改变
  • -
    用于避免以
    -
    开头的路径出现问题
  • 之所以有
    >/dev/null
    ,是因为
    cd
    可以根据shell选项打印当前路径
  • 我使用的是
    dirname
    ,因为其他所有东西都需要特殊功能,而这些功能并非无处不在。这意味着一个过程必须被分叉,但这种情况只会发生一次
  • pwd
    打印绝对路径

适用于查看当前脚本文件夹的人

1.sh

#!/bin/sh
if [ "$BASH_SOURCE" != "" ]
then
    DIR="$( cd "$( dirname "$BASH_SOURCE" )" && pwd )"
elif [ "$DASH_SOURCE" != "" ]
then
    DIR="$( cd "$( dirname "$DASH_SOURCE" )" && pwd )"
else
    DIR="$( cd "$( dirname "$0" )" && pwd )"
fi
echo $DIR
将产生以下结果:

cd ~
docker@boot2docker:~$ sh ./test/1.sh 
/home/docker/test
docker@boot2docker:~$ ./test/1.sh 
/home/docker/test
docker@boot2docker:~$ source ./test/1.sh 
/home/docker

如果有人知道如何处理
源代码,请在下面发表评论。

据我所知,/bin/sh是指向/bin/bash的符号链接。因此,您的问题中的解决方案被应用了。@silent:在Ubuntu上没有,其中/bin/sh是Dash,它是一个比Bash简单得多的shell。他们一两年前改变了这个。啊,好的。我不知道。在很多其他系统上也不知道,例如,/bin/sh可能是指向ksh的符号链接,或者是实际的Bourne shell。这必须是
$(dirname--“$0”)
,否则会出错。谢谢,我已经添加了您建议的双破折号,以避免dirname将路径解释为参数。
dirname
不是POSIX,可能在所有系统上都不可用。OP使用Ubuntu,dirname肯定在那里。您认为${0%/*}在破折号中工作吗?是的,这是POSIX参数扩展<代码>$0
不可靠,而且并非每个系统都提供
readlink
。我不明白您的答案,您能为我详细说明一下吗?嗯,这是一个发人深省的答案。谢谢。下面的其他答案在大多数情况下都适用,但重要的是要记住,对于100%的情况,没有万无一失的方法。很好的参考资料。@Aaron感谢--,我不知道它的存在,正在寻找这样的功能!
#!/bin/sh
if [ "$BASH_SOURCE" != "" ]
then
    DIR="$( cd "$( dirname "$BASH_SOURCE" )" && pwd )"
elif [ "$DASH_SOURCE" != "" ]
then
    DIR="$( cd "$( dirname "$DASH_SOURCE" )" && pwd )"
else
    DIR="$( cd "$( dirname "$0" )" && pwd )"
fi
echo $DIR
cd ~
docker@boot2docker:~$ sh ./test/1.sh 
/home/docker/test
docker@boot2docker:~$ ./test/1.sh 
/home/docker/test
docker@boot2docker:~$ source ./test/1.sh 
/home/docker