美文网首页Shell语言用例
bash脚本里如何得到脚本文件所在路径

bash脚本里如何得到脚本文件所在路径

作者: CodingCode | 来源:发表于2018-11-21 11:02 被阅读0次

    bash脚本里如何得到脚本文件所在路径

    应用背景

    我们在脚本里面会经常调用外部程序,如何指定外部程序路径:

    1. 绝对路径写死;缺点是不方便移植,比如更改安装路径等。
    2. 加到PATH搜索目录下面;缺点是PATH路径会被替换,同名程序的存在会导致调用到另一个程序。

    而有时,我们希望被调用的外部程序是相对当前脚本文件的,例如和脚本文件在同一目录下面,或者临近相对的子目录等等;

    |-- ROOT
    |-- mains.h
    |   |-- scripts
    |   |   |-- sub1.sh
    |   |   |-- sub2.sh
    |   |-- tools
    |   |   |-- tool1
    |   |   |-- tool2
    

    例如main.sh是主脚本,它需要调用scripts/sub.sh,tools/tool1,和tools/tool2,此时如果把所有的路径(ROOT:ROOT/scripts:ROOT/tools)都加到PATH里面显得有点重,那么我们只想把ROOT加到PATH里面,然后让main.sh来去搜索sub.sh和tool。

    思路

    这种场景下,我们就需要在main.sh里面得到脚本自己所在的路径(例如,SCRIPTDIR),然后按如下方式调用子程序:

    ${SCRIPTDIR}/scripts/sub.sh
    ${SCRIPTDIR}/tools/tool
    

    方法

    如何得到main.sh脚本所在的路径呢,下述命令可以得到:

    SCRIPTDIR=$(cd $(dirname "${BASH_SOURCE[0]}") >/dev/null && pwd)
    
    1. 例子1:

    假设脚本main.sh所在的路径是/home/<username>/main.sh

    $ cat main.sh 
    #!/bin/bash
    
    SCRIPTDIR=$(cd $(dirname "${BASH_SOURCE[0]}") >/dev/null && pwd)
    
    echo ${SCRIPTDIR}
    $ pwd
    /home/<username>/tmp
    $ ./main.sh 
    /home/<username>/tmp
    $ cd ..
    $ pwd
    /home/<username>
    $ ./tmp/main.sh 
    /home/<username>/tmp
    

    我们可以看到,不管当前的路径在哪里,调用起main.sh的时候它都能打印出脚本所在的路径。

    再看一个例子。

    1. 例子2:
    $ pwd
    /home/<username>
    $ ln -snf tmp/main.sh main.sh
    $ ./main.sh 
    /home/<username>
    

    我们创建一个符号链接,main.sh链接到tmp/main.sh,然后我们运行外层的main.sh这个符号链接,结果我们看到:打印出来的是符号链接文件所在的路径,而不是脚本所在的路径。

    这是合理的设计行为,因为我们调用的是外面的main.sh这个链接文件,但是对我们的需求就有问题了,因为在main.sh这个真正脚本里面就没法调用到子命令sub.sh和tool了,无法根据外面符号链接的路径来找scripts和tools路径了。

    解决办法呢,我们要不停的解决符号链接行为,直到遇到真正的脚本为止。
    重新改写tmp/main.sh脚本如下:

    #!/bin/bash
    
    #SCRIPTDIR=$(cd $(dirname "${BASH_SOURCE[0]}") >/dev/null && pwd)
    SOURCE="${BASH_SOURCE[0]}"
    while [ -h "${SOURCE}" ]; do
      SCRIPTDIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null && pwd)"
      SOURCE="$(readlink "${SOURCE}")"
      [[ ${SOURCE} != /* ]] && SOURCE="${SCRIPTDIR}/${SOURCE}"
    done
    SCRIPTDIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null && pwd)"
    
    echo ${SCRIPTDIR}
    

    再次运行符号链接文件:

    $ pwd
    /home/<username>
    $ ln -snf tmp/main.sh main.sh
    $ ./main.sh 
    /home/<username>/tmp
    

    这回打印出来的就是真正的脚本文件所在的路径了。

    相关文章

      网友评论

        本文标题:bash脚本里如何得到脚本文件所在路径

        本文链接:https://www.haomeiwen.com/subject/iiyqqqtx.html