如何获取其中的目录路径的 Bash脚本所在,该脚本里面 ?
例如,假设我想使用 Bash 脚本作为另一个应用程序的启动器。我想将工作目录更改为 Bash 脚本所在的目录,因此我可以对该目录中的文件进行操作,如下所示:
$ ./application
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
是一个有用的单行程序,它将为您提供脚本的完整目录名称,无论它在何处被调用。
只要用于查找脚本的路径的最后一个组件不是符号链接(目录链接正常),它就会起作用。如果您还想解决脚本本身的任何链接,您需要一个多线解决方案:
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && 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" )" >/dev/null && pwd )"
最后一个将适用于别名, source
, bash -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"
但是,正如matt 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