Bash脚本协助查找

时间:2017-07-09 06:25:47

标签: git bash

我正在尝试编写一个由每日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 `>'

4 个答案:

答案 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两次。

您可以通过删除临时文件并使用pushdpopd而不是cd some/pathcd -来简化脚本。

#!/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更改了当前路径,也不会改变当前路径。