サブディレクトリの git リポジトリに対してコマンド一括実行
サブディレクトリの 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
- https://git-scm.com/docs/git
- https://tracpath.com/docs/
- https://linuxjm.osdn.jp/html/GNU_findutils/man1/xargs.1.html
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