Shell脚本执行不再受限,不进入所在目录也能成功运行
通过使用dirname命令获取脚本执行时的文件路径,并在脚本中进入该目录,你可以确保无论脚本在哪里执行,都能够找到所需的文件。
这种方法可以应用于调用同目录下的其他Shell脚本或使用相对路径访问其他文件的情况
下面通过一个简单的示例来演示这种方法。假设在当前目录下,有一个位于bin目录的名为start.sh
的脚本,它需要调用同样位于bin目录的名为other.sh的脚本。可以使用以下代码
# 进入脚本所在的目录
cd $(dirname $0)
# 调用其它脚本
./other.sh
上述代码片段中,$0
表示当前脚本被执行时的名称,dirname
命令从该名称中获取脚本所在目录,$()
表示执行括号内的命令并且获得命令的返回结果。$(dirname $0)
将得到该脚本相对于当前目录的相对路径。
因此,无论是在当前目录执行“bin/start.sh
”,还是进入bin
目录后执行“./start.sh
”,脚本都能正常调用到other.sh
。
还可以进一步优化该方案。如果在其它路径创建了start.sh
的符号链接,此时就需要获取该符号链接的目标文件地址。可以使用readlink命令来实现。以下是优化后的代码
# 判断是否为符号链接
ftype=$(ls -l $0|cut -c 1)
if [[ $ftype == l ]];then
# 如果是符号链接,获取其目标文件地址
path=$(readlink $0)
else
# 否则直接使用当前文件路径
path=$0
fi
# 进入脚本所在的目录
cd $(dirname $path)
不过还有一点需要注意,readlink只是获取它接受的参数指定的符号链接的目标文件,如果该目标文件仍然是一个符号链接,则需要继续使用readlink获取目标文件。
可以将这部分封装成一个函数并递归调用,以下是该函数示例:
# 递归调用readlink获取符号链接的最终目标文件
rrl() {
ftype=$(ls -l $1|cut -c 1)
if [[ $ftype == l ]];then
# 如果是符号链接,递归获取其目标文件地址
echo $(rrl $(readlink $1))
else
# 否则直接使用当前文件路径
echo $1
fi
}
# 进入脚本所在的目录
cd $(dirname $(rrl $0))
通过这种方式,可以确保无论是在当前目录执行还是通过符号链接执行,脚本都能正常运行并成功调用或访问预期的文件