このスクリプトはすべてのgitリポジトリを取得します。
#!/bin/bash
find / -type d -name .git 2>/dev/null |
while read gitFolder; do
if [[ $gitFolder == *"/Temp/"* ]]; then
continue;
fi
if [[ $gitFolder == *"/Trash/"* ]]; then
continue;
fi
if [[ $gitFolder == *"/opt/"* ]]; then
continue;
fi
parent=$(dirname $gitFolder);
echo "";
echo $parent;
(git -C $parent pull && echo "Got $parent") &
done
wait
echo "Got all"
wait
すべてのサブシェルを待たないでくださいgit pull
。
なぜこれが起こるのですか?どうすれば解決できますか?
答え1
問題はwait
無効なシェルプロセスによって実行されています。では、bash
パイプラインの各部分が別々のサブシェルで実行されます。バックグラウンドジョブはwhile
ループを実行するサブシェルに属します。このサブシェルに移動すると、期待wait
どおりに機能します。
find ... |
{
while ...; do
...
( git -C ... && ... ) &
done
wait
}
echo 'done.'
あなたも少し持っています。引用符なし変数。
パイプを完全に取り外し、代わりにループを直接実行してくださいfind
。これにより、出力を解析する必要がなくなります。find
。
find / -type d -name .git \
! -path '*/Temp/*' \
! -path '*/opt/*' \
! -path '*/Trash/*' \
-exec sh -c '
for gitpath do
git -C "$gitpath"/.. pull &
done
wait' sh {} +
または、-prune
処理したくないサブディレクトリに移動したくない場合は、次のようにします。
find / \( -name Temp -o -name Trash -o -name opt \) -prune -o \
-type d -name .git -exec sh -c '
for gitpath do
git -C "$gitpath"/.. pull &
done
wait' sh {} +
説明で述べたように、xargs
同時に実行されるプロセスの数をよりよく制御することもできますgit
。以下で使用されるオプション-P
(同時ジョブ数の指定)は、非標準、-0
(読み取り\0
- 区切りパス名)、および-r
(入力なしでコマンドを実行しない)です。ただし、GNUxargs
とこのユーティリティの他のいくつかの実装にはこれらのオプションがあります。さらに、述語(出力で区切られたパス名)は非-print0
標準ですが、通常は実装されています。find
\0
find / \( -name Temp -o -name Trash -o -name opt \) -prune -o \
-type d -name .git -print0 |
xargs -t -0r -P 4 -I {} git -C {}/.. pull
私はGNUが同様の方法で使用できると確信していますparallel
が、それがこの質問の主な焦点ではないので、私はそのような考え方を追求しません。