【发布时间】:2018-10-22 08:38:40
【问题描述】:
此问题与:Getting the source directory of a Bash script from within 有关 - 在该问题中,有一个完美的答案显示 show 以获取当前运行的 bash 脚本的目录(包括读取符号链接的实际位置)。
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 )"
这很好用,除了它是很多样板代码。我正在开发一个脚本包,其中包含许多相互使用的小脚本。此脚本包托管在 git 存储库中,它必须与位置无关。例如。无论它被克隆到哪个目录,它都应该始终以相同的方式工作。必须能够将此 repo 克隆到许多不同的目录中并独立使用它们。许多脚本只是命令的包装器,或者它们正在调用在同一目录中或相对于包含目录的其他脚本。例如,这是一个模拟 'mongo' 命令的命令,但在 docker 容器中运行它:
#!/bin/bash
set -e
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 )"
# mongo-container is another script that determines the container id
# and it must be referenced relatively to the containing directory
MONGOE="docker exec -ti `${DIR}/mongo-container`"
${MONGOE} mongo "$@"
这段代码90%用于确定脚本的目录,只有10%做了一些有用的事情。我有大约 20 个这样的脚本。这意味着我 90% 的 bash 脚本只是“确定包含目录”。当我看着它们时,我几乎看不到它们在做什么,因为有太多的样板代码。一定有更好的方法,我就是想不通。
有什么想法吗?
【问题讨论】:
-
大部分代码仅用于解析符号链接。你真的需要那个吗?我认为
dirname "$0"对你来说应该足够了。 -
这些小脚本将被符号链接到系统上各个用户的 ~/bin 目录。所以是的,阅读符号链接很重要。
-
我很确定你不会得到比你链接的问题更好的结果。如果您需要重用代码,您可以在系统范围的函数或别名中声明它,甚至只是在主脚本执行之前系统调用的外部脚本
-
通常情况下,当您安装代码时,您可以通过将代码放在众所周知的位置来避免这种情况,而不是让脚本找出您放置它的随机目录。
-
你们都在说创建与位置无关的代码是个坏主意。脚本的位置是环境,脚本可以使用它。它只是碰巧在 bash 中很笨拙。它证明 bash 不是完成这项任务的完美工具。但这并不能证明与位置无关的代码不好。是否有充分的理由不编写与位置无关的代码?我不明白为什么“应该避免相对路径”?也许他们应该是,但我需要一个解释。
标签: bash