🚀

サブディレクトリの git リポジトリに対してコマンド一括実行

2022/10/30に公開

サブディレクトリの git リポジトリに対してコマンド一括実行

カレントディレクトリ以下に A, B というディレクトリがあり、その下に git リポジトリが複数あるような状況を想定する。

./A/a/.git
./A/b/.git
./A/c/.git
./B/a/.git
./B/b/.git
./B/c/.git

コマンド

find . -maxdepth 3 -name ".git" 2> /dev/null | xargs -r -n1 dirname | xargs -r -I{} sh -x -c "git -C {} remote update -p"

説明

find

-maxdepth 3 を指定して find を実行する。

ここで最大の深さを指定するのは、必要以上に深くディレクトリを検索しないためで、これよりディレクトリの階層が深い場合はもっと大きな値を指定するか、単に指定しなければよい。

ただしその場合、検索に時間がかかることに注意。

$ find . -maxdepth 3 -name ".git"
./B/c/.git
./B/b/.git
./B/a/.git
./A/c/.git
./A/b/.git
./A/a/.git

dirname

xargs とともに dirname を使用して、 .git ディレクトリのおかれているディレクトリ名を取り出す。

ここで xargs の引数に -n1 を指定しているが、dirname コマンドは引数を1つしか受け取らないので xargs が dirname を呼び出すときに 1つずつ呼び出すように指定する。
xargs に -r を指定することにより、標準入力が空だった場合にエラーにならないように xargs の処理を実行しないようにする。

$ find . -maxdepth 3 -name ".git" |  xargs -r -n1 dirname
./B/c
./B/b
./B/a
./A/c
./A/b
./A/a

git

git コマンドは -C オプションを指定することで作業ディレクトリを指定できる。
xargs の -I オプションを使うことで、指定したパターンを置換させるようにできる。

以下の例の場合 -I {} を指定しているので {} の部分を標準入力からの入力に置換できる。

xargs  -r -I{} git -C {} remote update -p

find と xargs を組み合わせる

以下のコマンドで .git のディレクトリまでの階層が 3 階層までのディレクトリを走査して、git remote update -p を実行できる。

find . -maxdepth 3 -name ".git" | xargs -r -n1 dirname | xargs -r -I{} git -C {} remote update -p

xargs で実行するコマンドを表示する

上記だとどのディレクトリを更新するのかわからないので、以下のように sh -x -c 経由で実行することにより、どのディレクトリを更新しているのか、表示できる。

find . -maxdepth 3 -name ".git" | xargs -r -n1 dirname | xargs -r -I{} sh -x -c "git -C {} remote update -p"

find で permission のエラーが出る場合に無視する

2> /dev/null で標準エラー出力を捨てて、permission などのエラーが表示されないようにする。

find . -maxdepth 3 -name ".git" 2> /dev/null | xargs -r -n1 dirname | xargs -r -I{} sh -x -c "git -C {} remote update -p"

Discussion