我正在尝试编写一个由每日cron调度调用的bash脚本,该调度将循环查找.git目录的所有子目录,在该存储库上运行git pull --all
以更新repo并抓取任何新的分支,跟踪这些分支,然后继续下一个回购。我是一个bash脚本的初学者,熟悉一些linux。我的问题是我在How to clone all remote branches in Git?找到的for循环,但由于我已将其引入我的脚本并调用cd ${line}..
并且没有#39},因此似乎无法正常运行;似乎按预期工作。我想知道我做错了什么,以及如何解决它的方向。谢谢。
我当前的脚本gitcron.sh:
#!/bin/bash
find . -maxdepth 2 -name .git -type d -print > .gitrepos
while read -r line; do
cd ${line}/..
git pull --all
for branch in $(git branch --all | grep '^\s*remotes' | egrep --invert-match '(:?HEAD|master)$'); do
git branch --track "${branch##*/}" "$branch"
done
done < ".gitrepos"
.gitrepos生成的文件:
./codeigniter/.git
./magento/.git
./magento2/.git
我的问题:
gitcron.sh: line 6: cd: ./magento2/.git/..: No such file or directory
fatal: it does not make sense to create 'HEAD' manually
error: unknown switch `>'
答案 0 :(得分:2)
问题是您已使用cd ${line}/..
更改了工作目录(并不断更改),即转到{line}
的父级。一切都在同一个shell会话中完成。首次运行后,目录将更改为line
变量的第一个值的父级,因此下一次运行(prsumably)会因为未能找到父级而失败(因此.git
也不会出现。)
要解决此问题,您可以:
使用find
目录中的绝对路径:
find /foo/bar/ ...
然后立即使用while
。
或者在子shell中运行cd
和连续的块:
while ...; do (cd ...; ...); done <file
作为旁注,(总是)引用您的变量扩展以防止分词和路径名扩展。
答案 1 :(得分:1)
问题是您已经在codeigniter
循环中使用cd
将目录更改为第一个回购,即while
。之后,您的脚本最终不会使用cd -
返回父目录。
您甚至可以使用流程替换来避免临时文件创建:
while IFS= read -d '' -r line; do
cd "$line"/..
git pull --all
while read -r branch; do
git branch --track "${branch##*/}" "$branch"
done < <(git branch --all | grep '^\s*remotes' | egrep --invert-match '(:?HEAD|master)$')
cd -
done < <(find . -maxdepth 2 -name .git -type d -print0)
答案 2 :(得分:1)
正如其他用户已经发布的那样,问题似乎是没有使用绝对目录和cd
两次。
您可以通过删除临时文件并使用pushd
和popd
而不是cd some/path
,cd -
来简化脚本。
#!/usr/bin/env bash
set -uo pipefail
find . -maxdepth 2 -name ".git" -type d -print0 | while IFS= read -r -d '' repo; do
# Use bash parameter substitution to remove .git from end of path
pushd "${repo%.git}" >/dev/null
# Could also use dirname to get the parent directory
#pushd "$( dirname "$repo" )" >/dev/null
# Now in correct directory; run all git commands"
# git ...
popd >/dev/null
done
答案 3 :(得分:0)
作为一种解决方法,请尝试使用相同的find命令,但使用绝对路径:
find $(pwd) -maxdepth 2 -name .git -type d -print > .gitrepos
这样,cd
将通过完整而完整的路径访问这些文件夹
即使您的第一个cd
更改了当前路径,也不会改变当前路径。