使用另一个目录的相对路径运行脚本

Jon*_*ona 3 linux bash relative-path

我正在编写一个脚本来编译代码.这些来源位于许多不同的目录中.我将发布源代码,我希望它可以被许多其他人编译.因此在我的脚本中我使用相对路径.
如果有人在他的机器上运行脚本,则从脚本所在的目录中运行,就像./script一切正常.但是,如果脚本是从另一个目录运行的,./path/to/script那么路径不正确并且脚本不起作用.
我怎么能克服这个?

hme*_*ia1 6

一个简单的起点可能是将其添加到脚本的顶部:

#!/bin/bash
scriptdir="$(dirname "$0")"
cd "$scriptdir"
Run Code Online (Sandbox Code Playgroud)

以下所有代码都将在脚本目录中运行.

请注意,这是关于导致脚本运行

  • 从脚本所在的文件夹,和
  • 无论从最初调用脚本的位置如何

这是我怀疑你想要的,因为它是一个用于编译的脚本,因此它将被放置在src树中的一个非常特定的文件夹中(例如configure脚本或makefile的形式)

合理

  • $0 是运行脚本的完整路径.

    • bash男人(我添加的格式):

      特殊参数

      shell专门处理几个参数.这些参数只能被引用; 不允许分配给他们.
         ....

      0    扩展为shell或shell脚本的名称.这是在shell初始化时设置的.
         如果使用命令文件调用bash,则将 $ 0 设置为该文件的名称.

         如果使用该-c选项启动bash ,则将$ 0设置
         为要执行的字符串之后的第一个参数(如果存在).否则,它被设置为
         用于调用bash 的文件名,如参数0所示.

  • dirname 返回其参数的路径

  • cd 更改当前目录

因此,顶部具有此代码的每个脚本都将运行,就像./script当前在该目录中一样.

从另一个角度来看它

对于质量控制和冗余错误检查的度量,您可能希望实现一个包装函数,该函数检查特定文件夹结构或某些文件的存在,以指示一切正确.(不管出于什么原因说这个dirnamecd命令都不起作用 - 我在这篇帖子的底部有一个关于Mac的例子).这个概念有两个方面:

  1. 你正在做的事情来设置当前目录
  2. 你正在检查你所做的事情是否有效.

例如:

runcheck () {
versioncheck () {

head -n1 version | grep -q "### myapp V"

}

backout () {
echo "Problem verifying source paths.  Are you sure your archive is complete?"
exit
}

[ -d ./src ] && [ -d ./docs ] && [ -d ../myapp ] && (versioncheck) || backout 
    return
}
Run Code Online (Sandbox Code Playgroud)

该代码将检查以下内容:

  • 该目录src与可执行脚本存在于同一路径中
  • 该目录docs与可执行脚本存在于同一路径中
  • 该目录myapp存在于从可执行脚本向下一级的路径中
  • 这有一个名为version作为可执行脚本相同的路径,并且它的第一行包含字符串### myapp V(例如,对于version其中可能有一个顶线读取文件:### myapp V1.4 ###)

然后,您可以将命令runcheck放在脚本中的任何位置,以确保您位于正确的位置:

完整的实施示例:

#!/bin/bash

scriptdir="$(dirname "$0")"
cd "$scriptdir"

runcheck () {
versioncheck () {
    head -n1 version | grep -q "### myapp V"
}   

backout () {
    echo "Problem verifying source paths.  Are you sure your archive is complete?"
    exit
}

[ -d ./src ] && [ -d ./docs ] && [ -d ../myapp ] && (versioncheck) || backout 
    return
}

runcheck #initial check at start of script

## bunch of code
## goes here

runcheck #just checking again

## bunch of code
## goes here

runcheck #final check before really doing something bad

## end of script
Run Code Online (Sandbox Code Playgroud)

附注/补充:这将适用于bash不需要进行彻底检查以解释脚本文件的符号链接等.(再次......在便携式源代码tarball等中,我非常怀疑是这种情况).

我建议阅读这个主题: 如果你想要或者需要彻底了解这个主题,从内部获取Bash脚本的源目录,以获得更全面的应用程序.

我再次使用您所知道的为您所需要的东西重新使用 - 例如,它可能被认为通常更"强大"使用dirname "$(readlink -f "$0")",但是,在Mac OS X上,这将给你readlink: illegal option -- f,并且对于可移植脚本没有任何实际好处但更适用于引用已安装的二进制文件的位置,这些二进制文件可以符号链接和/或包含在$ PATH目录中

  • @Jona是的,每个运行实例,无论是相同的脚本还是其他脚本,顶部的那些行都只有`$ scriptdir`仅适用于该文件.*即使*由于某些疯狂的原因,`$ scriptdir`是父shell中的导出环境变量,脚本中的`$ scriptdir`设置仍将更新该脚本的值(而不是父shell环境) (2认同)
  • @Jona我添加了一个额外的补充,可能有助于检查scriptdir和后续当前目录的设置在执行任何实际命令之前都运行良好.您显然会修改它以适合您的项目 (2认同)