Improve a script to generally check status of several git repos I've tried to write a bash script that gives me a general overview of the status of git repos I have cloned/created. It's not meant to replace git status by any means, but give an overview of several repos. 

Keep in mind I'm not the most knowledgeable about bash scripting AND git, so I imagine there is a better way to do this:

#!/bin/bash
# Help from: http://www.leancrew.com/all-this/2010/12/batch-comparison-of-git-repositories/

index=0
gitrepos=()

#TODO: There has got to be a better way to add all these folders to the array
#add repos folder
for d in ~/repos/*; do
    gitrepos[(index+=1)]="$d"
done

#add other important folders
gitrepos[(index+=1)]=~/.vim
gitrepos[(index+=1)]=~/dot_files
gitrepos[(index+=1)]=~/bin

for d in "${gitrepos[@]}"; do
    if [ -e $d ]; then
        cd $d
    else
        echo " Did not find repo: $d"
        continue
    fi

    reponame="`basename $d`"

    ok=true
    git fetch --quiet origin 2&gt;/dev/null
    if [ ! -z "`git diff HEAD origin/HEAD 2&gt; /dev/null`" ]; then
        echo " $reponame --&gt; Out of sync with origin/HEAD"
        ok=false
    fi
    if [ ! -z "`git ls-files --other --exclude-standard 2&gt; /dev/null`" ]; then
        echo " $reponame --&gt; Untracked files present"
        ok=false
    fi
    if [ ! -z "`git diff --cached --shortstat 2&gt; /dev/null`" ]; then
        echo " $reponame --&gt; Changes to be committed"
        ok=false
    fi
    if [ ! -z "`git diff --shortstat 2&gt; /dev/null`" ]; then
        echo " $reponame --&gt; Changes to be staged/committed"
        ok=false
    fi
    if $ok; then
        echo " OK --&gt; $reponame"
    fi
done
Yes there is a better way of filling an array. You can use globbing inside of array parens. Also I suggest being explicit about what you do in bash and use declare -a to declare arrays and later on declare for other variables

declare -a repos=(~/repos/* ~/.vim ~/dot_files ~/bin)


In case of adding stuff to an array, after it got created:

repos+=("more stuff" here)


Maybe you want to name you iterating variable more verbose, instead of d repodir or something.

Your first if contains a continue so you can emphasize on this one and just go on with no else. Also don't miss the double quotes in case of directory names with spaces in them. Also you should check for -d since you cd into it.

if [ -d "$d" ]; then
  echo "No repo at $d"
  continue
fi
cd "$d"


[ ! -z "`cmd`" ] is more verbose than it needs to be. You can just do [ "`cmd`" ].

Read the "Arrays" chapter in the bash manpage.

I attach my test file for this answer which also shows functions and some refactoring which allows to discard this ok variable.

#!/bin/bash
main() {
    local -a repos=(* /foo/bar)
    echo -e "repos: ${repos[@]}"
    for path in "${repos[@]}"; do
      check_repo "$path"
    done
}

check_repo() {
    local path="$1"
    local name="`basename "$path"`"
    local report=""
    if [ ! -d "$path" ]; then
      echo -e "$name\n not a directory: $path"
      return
    fi
    cd "$path"
    if [ "`echo foo 2&gt; /dev/null`" ]; then
        report+="\n oh oh"
    fi
    cd - &gt; /dev/null
    if [ -z "$report" ]; then
        report+="\n OK"
    fi
    echo -e "$name$report"
}

main