从内部获取Bash脚本的源目录

如何在该脚本中获取Bash脚本所在的目录的路径?

例如,假设我想使用Bash脚本作为另一个应用程序的启动器。 我想将工作目录更改为Bash脚本所在的目录,因此我可以对该目录中的文件进行操作,如下所示:

$ ./application

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

是一个有用的单行程序,无论它从哪里被调用,它都会给你脚本的完整目录名称。

只要用于查找脚本的路径的最后一个组件不是符号链接(目录链接正常),它就会工作。 如果您还想解析脚本本身的任何链接,则需要一个多线解决方案:

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"

最后一个可以与别名, sourcebash -c ,符号链接等组合使用。

请注意:如果您cd运行该段之前到不同的目录,其结果可能是不正确的! 另外,请注意$CDPATH陷阱。

要了解它如何工作,请尝试运行这个更详细的表单:

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  TARGET="$(readlink "$SOURCE")"
  if [[ $TARGET == /* ]]; then
    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
    SOURCE="$TARGET"
  else
    DIR="$( dirname "$SOURCE" )"
    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
    SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
  fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"

它会打印如下内容:

SOURCE './scriptdir.sh' is a relative symlink to 'sym2/scriptdir.sh' (relative to '.')
SOURCE is './sym2/scriptdir.sh'
DIR './sym2' resolves to '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'

使用dirname "$0"

#!/bin/bash
echo "The script you are running has basename `basename "$0"`, dirname `dirname "$0"`"
echo "The present working directory is `pwd`"

如果您没有从包含它的目录运行脚本,单独使用pwd将不起作用。

[matt@server1 ~]$ pwd
/home/matt
[matt@server1 ~]$ ./test2.sh
The script you are running has basename test2.sh, dirname .
The present working directory is /home/matt
[matt@server1 ~]$ cd /tmp
[matt@server1 tmp]$ ~/test2.sh
The script you are running has basename test2.sh, dirname /home/matt
The present working directory is /tmp

dirname命令是最基本的,只需将$ 0(脚本名称)变量之外的路径解析为文件名即可:

dirname "$0"

但是,正如马特b指出的那样,根据脚本的调用方式,返回的路径是不同的。 pwd不做这项工作,因为它只告诉你当前目录是什么,而不是脚本所在的目录。另外,如果执行到脚本的符号链接,你将得到一个(可能是相对的)路径到链接所在的位置,而不是实际的脚本。

其他一些人提到了readlink命令,但最简单的方法是,您可以使用:

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

readlink会将脚本路径解析为文件系统根目录的绝对路径。 因此,包含单点或双点,波浪线和/或符号链接的任何路径都将被解析为完整路径。

下面是一个脚本,演示其中的每一个, whatdir.sh:

#!/bin/bash
echo "pwd: `pwd`"
echo "$0: $0"
echo "basename: `basename $0`"
echo "dirname: `dirname $0`"
echo "dirname/readlink: $(dirname $(readlink -f $0))"

在我的主目录中运行此脚本,使用相对路径:

>>>$ ./whatdir.sh 
pwd: /Users/phatblat
$0: ./whatdir.sh
basename: whatdir.sh
dirname: .
dirname/readlink: /Users/phatblat

再次,但使用脚本的完整路径:

>>>$ /Users/phatblat/whatdir.sh 
pwd: /Users/phatblat
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

现在改变目录:

>>>$ cd /tmp
>>>$ ~/whatdir.sh 
pwd: /tmp
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

最后使用符号链接来执行脚本:

>>>$ ln -s ~/whatdir.sh whatdirlink.sh
>>>$ ./whatdirlink.sh 
pwd: /tmp
$0: ./whatdirlink.sh
basename: whatdirlink.sh
dirname: .
dirname/readlink: /Users/phatblat
链接地址: http://www.djcxy.com/p/183.html

上一篇: Getting the source directory of a Bash script from within

下一篇: How to check whether a checkbox is checked in jQuery?