【问题标题】:Making shell scripts robust against location they're called from使 shell 脚本对调用它们的位置具有鲁棒性
【发布时间】:2013-08-27 17:37:28
【问题描述】:

编写一个可以访问与它相关的文件的 shell 脚本的最佳方法是什么,这样我从哪里调用它并不重要? “简单”是指可以在不同系统/shell 上工作的最简单/推荐的方式。

示例

假设我有一个文件夹 ~/MyProject,其中包含子文件夹 scripts/files/。在scripts/ 中,我有一个shell 脚本foo.sh 想要访问files/ 中的文件:

if [ -f "../files/somefile.ext" ]; then
    echo "File found"
else
    echo "File not found"
fi

如果我使用cd ~/MyProject/scripts && ./foo.sh,它会正常工作,但它会因cd ~/MyProject && scripts/foo.sh 而失败。

【问题讨论】:

标签: linux bash shell zsh ksh


【解决方案1】:

不确定这对您来说是否足够简单,但这可以为您提供解决方案:

Shell Script Loader

【讨论】:

  • 我宁愿不安装额外的东西。我觉得编写可以从任何地方调用的 shell 脚本应该是非常基本的,但也许这是错误的。
  • @IngoBürk 好吧,这取决于你 :) 我做了这个项目毕竟是因为这种必要性。如果贝壳已经提供了这样的解决方案,那就没有必要了。您可以自己制作一个类似于我所拥有的嵌入式解决方案,但我敢打赌,复杂性将是相似的,除非您更喜欢使用 hacks,因为大多数情况下这会使脚本运行非常缓慢,因为很多subshel​​l 调用和对外部命令的调用。有时它也会使脚本在可读性方面更加混乱。顺便说一句,这些也是脚本,以防你不知道。
【解决方案2】:

将所有路径设为绝对路径。 尽可能使用环境变量,例如 $HOME。 您遇到了 UNIX 脚本的弱点。

使用 .profile 或 .bash_profile,您的开发人员可以设置一堆 ENV 变量。然后您的脚本可以利用这些变量。

在我工作的一个地方,您可以运行一个脚本,它会提示您要查看哪个版本,并设置 ENV,以便开发人员的交互非常无缝。

【讨论】:

  • 说它是一个 git repo 中的脚本。任何克隆它的人都会将它放在不同的文件夹中——我怎么知道任何绝对路径?
  • @Ingo:但是脚本怎么知道呢?只需将工作路径作为输入参数即可。
  • "脚本怎么知道?" – 我的意思是:) 我希望只有一个脚本选项,以便系统将它视为从它所在的目录调用它......
  • 你可以像上面提到的Pete一样使用环境变量。每个用户都可以在他/她的本地计算机中将其设置为正确的路径(一次)。
【解决方案3】:

你通常可以这样做:

mydir="$(dirname $0)"

获取运行脚本的目录。

然后使用它来定位您的文件。

【讨论】:

  • 这就是我目前所知道的方式。但是 SO 上的其他线程表明这在许多情况下会中断(可能是不同的系统或调用脚本的不同方式,比如采购它)。
  • 编辑问题以添加此类示例。目前你的问题太模糊了。 (至少你应该在一定程度上限制使用。太多的笼统不能做任何事情。)
【解决方案4】:
if [ -f "../files/somefile.ext"]
then
  echo "file was found"
else
  echo "file was not found"
fi

秒:

if [ ! -f /tmp/foo.txt ]; then
    echo "File not found!"
fi

【讨论】:

  • ……什么?我不知道你想告诉我什么,抱歉。
【解决方案5】:

考虑到$0应该包含执行脚本的路径,你可以简单地cd到它然后正常处理

所以你只需这样做

scriptDir=$(dirname -- "$0")
cd -- "$scriptDir"

但这仍然是一个 hack,您可能应该考虑一种使用绝对路径的方法

【讨论】:

    【解决方案6】:

    不幸的是,似乎没有一个真正通用的解决方案。我个人的建议(和实践)是只为提供一致访问权限的 shell 编写——最近的ksh93${.sh.file}bash$BASH_SOURCE 等。(我不知道@ 987654325@ 解决方案,但我确定有一个。)

    除此之外,最好的解决方案是以某种方式避免问题;例如,对于 git 存储库中的脚本示例,您可以要求从它所在的目录调用该脚本。通过检查 [[ -e myscript ]] 进行验证后,您可以预期相对链接将按预期工作。 (是的,为了完全的稳健性,您需要将脚本的基本名称硬编码到测试中,这与这个问题首先存在的原因相同——它在所有可能的情况下都可用于 shell。)

    【讨论】:

      猜你喜欢
      • 2011-01-18
      • 2018-06-16
      • 2013-02-24
      • 2017-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-27
      • 2021-09-17
      相关资源
      最近更新 更多