Script to execute arbitrary command on each Git project in a directory The idea is simple, most people have some one directory containing all their projects as subdirectories. When you are in the top directory and you run this script like so for-each-git.sh git status it will run the command git status in each of the folders. I have another script called git-ffwd that fetches all remotes and fast forward updates them which I usually run each morning with this script.

#!/bin/bash
for dir in $(find . -maxdepth 1 -type d); do
    (
        cd ${dir}
        if [ -d ".git" ]; then
            pwd
            "$@"
            echo
        fi
    )
done


Some explanation:


The parenthesis is so we are able to easily go back to the project directory in case the commands you push in run cd or something. (It makes a subshell.)
pwd is so we know for sure which directory is being worked on and the echo is just so a new line separates everything a little more.


I know this is a small script but I am new-ish to writing Bash scripts and want to learn.

The lines pwd; "$@"; echo seem a little ugly, though they do work. Also I can't pass multiple commands in with a ; like echo hey; echo bye because the ; ends the statement in the "$@" line, so I am wondering if there's a better way to write that line (or pass them in).
Instead of using find and testing whether .git is a directory, you could make a simplification:

for git_dir in */.git ; do
(
    cd "$git_dir/.." &amp;&amp;
    pwd &amp;&amp;
    $@
    echo
)
done


Admittedly, this causes an error when .git exists but is not a directory:


-bash: cd: blah/.git/..: Not a directory



… instead of silently skipping that entry as your script does.  But I would consider the error message to be a feature, not a bug.  =)  Note my use of &amp;&amp; after cd to ensure that the command is not executed if the cd fails.  (That could happen if the directory lacks the executable bit.)

If you wanted to support compound commands like echo hey; echo bye, you could use eval $@.  Using eval feels a bit risky, but it's OK if the script is for your own personal use and won't be attacked.