将bash脚本源到另一个[重复]

Posted

技术标签:

【中文标题】将bash脚本源到另一个[重复]【英文标题】:Source bash script to another one [duplicate] 【发布时间】:2012-12-23 14:49:24 【问题描述】:

可能重复:Reliable way for a bash script to get the full path to itself?

我有 bash 脚本 test.sh,它通过以下几行使用另一个 search.sh 脚本中的函数:

source ../scripts/search.sh
<call some functions from search.sh>

这两个脚本都位于 git 存储库中。 search.sh&lt;git_root&gt;/scripts/ 目录中,test.sh 位于同一目录中(但一般来说,可以位于&lt;git_root&gt; 目录内的任何位置 - 我的意思是我不能依赖以下source search.sh 方法)。

当我从&lt;git_root&gt;/scripts/ 调用test.sh 脚本时,一切正常,但是一旦我更改当前工作目录test.sh 失败:

cd <git_root>/scripts/
./test.sh         //OK
cd ..
./scripts/test.sh //FAILS
./scripts/test.sh: line 1: ../scripts/search.sh: No file or directory ...

这就是我所拥有的:

    search.sh 脚本到&lt;git_root&gt; 目录的相对路径

我想要什么:能够在&lt;git_root&gt; 内的任何地方运行test.sh 而不会出错。

P.S.:不能使用search.sh 的永久绝对路径,因为可以将 git 存储库克隆到任何位置。

【问题讨论】:

不重复。我尝试了此链接中的方法。但这不是我的情况,因为在这里我不需要获取我的 test.sh 脚本的路径。 也许我说的很明显,但是如果您目前source 是当前目录的相对路径,那么从脚本路径中获取相对路径似乎是一个很好的改进。唯一的问题是如果用户将脚本完全移动到不同的位置,但我无法想象你会如何解决这个问题,除了使用环境变量。 如果search.sh 脚本与test.sh 位于同一目录中,那么找到test.sh 所在的路径肯定会有所帮助,因为您可以使用该路径来查找其他脚本. 【参考方案1】:

如果两个脚本都在同一个目录中,那么如果你得到运行脚本所在的目录,你就可以用它作为调用另一个脚本的目录:

# Get the directory this script is in
pushd `dirname $0` > /dev/null
SCRIPTPATH=`pwd -P`
popd > /dev/null

# Now use that directory to call the other script
source $SCRIPTPATH/search.sh

取自问题的已接受答案,我将此问题标记为重复:https://***.com/a/4774063/440558

【讨论】:

似乎更容易做到SCRIPTPATH=$( readlink -f $0 )【参考方案2】:

有没有办法识别这个 Git 存储库位置?环境变量集?您可以在脚本本身中设置 PATH 以包含 Git 存储库:

 PATH="$GIT_REPO_LOCATION/scripts:$PATH"
 . search.sh

脚本完成后,您的 PATH 将恢复为旧值,$GIT_REPO_LOCATION/scripts 将不再是 PATH 的一部分。

问题是找到这个位置开始。我想你可以在你的脚本中做这样的事情:

GIT_LOCATION=$(find $HOME -name "search.sh" | head -1)
GIT_SCRIPT_DIR=$(dirname $GIT_LOCATION)
PATH="$GIT_SCRIPT_DIR:$PATH"
. search.sh

顺便说一句,既然设置了$PATH,我可以通过search.sh 调用脚本,而不是./search.sh,当你在脚本目录中时你必须这样做,而你的PATH 没有包括.,这是当前目录(PATH 不应该包括.,因为它是一个安全漏洞)。

另外请注意,您也可以搜索 .git 目录,这可能是您正在寻找的 Git 存储库:

GIT_LOCATION=$(find $HOME -name ".git" -type d | head -1)
PATH="$GIT_LOCATION:$PATH"
. search.sh

【讨论】:

但是如何避免类似 git 存储库的问题。不能保证有人做了git clone &lt;link&gt; first-git-repo 然后git clone &lt;link&gt; second-git-repo。同样在一般情况下,此解决方案可能会花费太多时间来搜索此 git 存储库。同样在一般情况下,我们不仅应该使用$HOME dir,还应该使用/ (root) dir。 出于这些原因,我简化了任务。即使对于这个也找不到可靠的方法;) 您在第二个代码块的第二行缺少右括号。 @user966467 好的,怎么知道 Git 存储库的位置?无论您找到该 Git 存储库的位置,都必须让您的程序知道。 我建议我可以使用@Joachim Pileborg 提到的meta.stackexchange.com/questions/14237207/…。【参考方案3】:

你可以这样做:

# Get path the Git repo
GIT_ROOT=`git rev-parse --show-toplevel`

# Load the search functions
source $GIT_ROOT/scripts/search.sh

How get Git root directory!

或者喜欢@Joachim Pileborg says,但是要注意一定要知道这个到另一个脚本的路径;

# Call the other script
source $SCRIPTPATH/../scripts/search.sh
# Or if it is in another path
source $SCRIPTPATH/../scripts/seachers/search.sh

Apache Tomcat 脚本使用这种方法:

# resolve links - $0 may be a softlink
PRG="$0"

while [ -h "$PRG" ] ; do
  ls=`ls -ld "$PRG"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '/.*' > /dev/null; then
    PRG="$link"
  else
    PRG=`dirname "$PRG"`/"$link"
  fi
done

PRGDIR=`dirname "$PRG"`

无论如何,你必须把这个sn-p放在所有使用其他脚本的脚本上。

【讨论】:

做任何其他方式,不使用可靠代码中的 git 功能,我必须使用 git 命令的存在性检查。我的意思是在每个新脚本中我都必须使用一些重复的代码:检查git 的存在,获取GIT_ROOT,等等... 如果用户不在 Git 存储库中怎么办?有没有办法找到 Git 本地存储库? @DavidW。找到 Git 本地存储库最可靠的方法是在目录结构中向上移动,直到找到 .git 目录或找到某个已定义的目录,例如 $HOME/ 等。 @sigmavirus24 我从 OP 中得知他正在使用的目录可能在 Git 存储库本身之外。例如,他在$HOME/bin,但Git repo 在$HOME/work/git_repo 来自 OP:Both scripts are located in git repository. ... What I want: To have ability to run test.sh from anywhere inside &lt;git_root&gt; without errors.【参考方案4】:

对于那些不想使用 git 的功能来查找父目录的人。如果你可以确定你总是在 git 目录中运行脚本,你可以使用这样的东西:

git_root=""
while /bin/true ; do
    if [[ "$(pwd)" == "$HOME" ]] || [[ "$(pwd)" == "/" ]] ; then
        break
    fi

    if [[ -d ".git" ]] ; then
        git_root="$(pwd)"
        break
    fi

    cd ..
done

我还没有对此进行测试,但它只会循环返回,直到它到达您的主目录或 / 并且它会查看每个父目录中是否有 .git 目录。如果有,它会设置git_root 变量并且它会爆发。如果找不到,git_root 将只是一个空字符串。然后你可以这样做:

if [[ -n "$git_root" ]] ; then
    . $git_root/scripts/search.sh
fi

IHTH

【讨论】:

以上是关于将bash脚本源到另一个[重复]的主要内容,如果未能解决你的问题,请参考以下文章

将 ssh 登录发送到 Mattermost 的 bash 脚本的问题 [重复]

将数组从一个 Bash 脚本传递到另一个

bash 脚本中的源文件

bash -- 杀死命令脚本 [重复]

将python脚本的输出返回到bash变量[重复]

在 bash 脚本中导出数组