Bash 在与当前脚本相同的目录中运行脚本

Bash 在与当前脚本相同的目录中运行脚本,bash,path,filepath,Bash,Path,Filepath,我在同一文件夹中有两个Bash脚本(由下载整个存储库的用户保存在某处): script.sh由用户运行 help.sh是必需的,由script.sh 这两个脚本应该在同一个目录中。我需要第一个脚本来调用第二个脚本,但存在两个问题: 知道当前工作目录对我来说毫无用处,因为我不知道用户是如何执行第一个脚本的(可以是/usr/bin/script.sh,也可以是/script.sh,也可以是。/Downloads/repo/scr/script.sh) 在调用helper.sh之前,脚本scrip

我在同一文件夹中有两个Bash脚本(由下载整个存储库的用户保存在某处):

  • script.sh
    由用户运行
  • help.sh
    是必需的,由
    script.sh
这两个脚本应该在同一个目录中。我需要第一个脚本来调用第二个脚本,但存在两个问题:

  • 知道当前工作目录对我来说毫无用处,因为我不知道用户是如何执行第一个脚本的(可以是
    /usr/bin/script.sh
    ,也可以是
    /script.sh
    ,也可以是
    。/Downloads/repo/scr/script.sh
  • 在调用
    helper.sh
    之前,脚本
    script.sh
    将更改为其他目录
  • 我可以通过存储在一个变量中,将Bash整合到一起,但代码似乎不必要地复杂,因为我认为这是一项非常常见和简单的任务


    是否有一种标准方法可以从
    script.sh
    中可靠地调用
    helper.sh
    ?并且将在任何Bash支持的操作系统中工作?

    由于
    $0
    保存正在运行的脚本的完整路径,因此可以对其使用以获取脚本的路径:

    #!/bin/bash
    
    script_name=$0
    script_full_path=$(dirname "$0")
    
    echo "script_name: $script_name"
    echo "full path: $script_full_path"
    
    例如,如果将其存储在
    /tmp/a.sh
    中,则会看到如下输出:

    $ /tmp/a.sh
    script_name: /tmp/a.sh
    full path: /tmp
    
    所以

  • 知道当前工作目录对我来说毫无用处,因为我不知道用户是如何执行第一个脚本的(可能是
    /usr/bin/script.sh
    ,带有
    /script.sh
    ,也可以带有
    。/下载/repo/scr/script.sh
  • 使用
    dirname“$0”
    可以跟踪原始路径

  • 在调用
    helper.sh
    之前,脚本
    script.sh
    将更改为其他目录

  • 同样,由于您在
    $0
    中有路径,因此可以
    cd
    返回该路径。

    $0
    被许多开发人员考虑和使用。我找到了另一个解决方案,它对于bash脚本链和
    源代码
    是安全的

    如果
    a.sh
    需要使用bash进程执行
    b.sh
    (位于同一文件夹中):

    #!/bin/bash
    __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    bash ${__dir}/b.sh
    
    #!/bin/bash
    __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    source ${__dir}/b.sh
    
    如果
    a.sh
    需要使用相同的bash进程执行
    b.sh
    (位于同一文件夹中):

    #!/bin/bash
    __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    bash ${__dir}/b.sh
    
    #!/bin/bash
    __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    source ${__dir}/b.sh
    
    是否有一种从内部可靠调用
    helper.sh
    的标准方法
    script.sh
    ?在任何Bash支持的操作系统中都能工作吗

    大多数情况下,当
    helper.sh
    script.sh
    位于同一目录时,您可以在
    script.sh
    中使用以下命令:

    . ${0%/*}/helper.sh
    
    说明:
    $0
    存储进程的名称(在大多数情况下它是脚本的完整路径)。
    ${parameter%word}
    从变量
    $parameter
    中删除后缀模式
    word
    (在上面的命令中,它从变量
    $0
    中存储的完整路径中删除文件名
    /*

    如果出于某些原因(在其他答案中描述)您不想使用
    $0
    ,您可以使用
    $BASH\u SOURCE

    . ${BASH_SOURCE%/*}/helper.sh
    
    如果需要,您可以使用
    源代码
    而不是

    source ${BASH_SOURCE%/*}/helper.sh
    

    对我来说,这是实现目标最简单的方法。

    您可以使用
    $0
    变量。但这并不像获取当前脚本名称那么简单:

    d=${0%/*}
    [x“$d”=x“$0”]&&d=。#便携式变体,在bash中自由使用[…]
    只读d#可选,以增加安全性
    # ... 后来
    . “$d”/helper.sh
    

    这在
    set-e
    情况下也能很好地工作。

    简单地说,使用
    $0
    不会像脚本源那样工作。对于bash,有
    bash\u源代码
    备选方案。您的链接指向已删除的注释。您是否有其他来源支持不安全索赔?相关帖子解释了
    $0
    :,。@CrisLuengo认为这是链接:
    [x“$d”=x“$0”]
    语法是什么?在等式运算符的参数之前,
    x
    的语法功能是什么。或者在下面的习语
    [-z${var+x}]
    ?@vonspotz回答第一个问题:如果
    $0
    $d
    以hypen开头,它可以避免可能导致的错误,否则它将被解释为
    […]
    命令的指令。@vonspotz回答第二个问题:
    ${var+x}
    表示“如果设置了
    $var
    ,则替换为
    x
    ”。即使
    $var
    为空,也会导致
    x
    字符串被替换。但如果根本没有设置
    $var
    ,则不会替换任何内容。因此,这与
    [x“$foo”=x“$bar”]
    问题完全不同。