Faire une boucle dans les sous-répertoires et exécuter une commande dans chacun

47

J'ai un ensemble de référentiels triés dans des répertoires basés sur leur VCS (Git, Mercurial, SVN). Avec Subversion, je pouvais m'exécuter svn update *dans le répertoire parent, qui parcourait chaque répertoire et mettait à jour chaque référentiel comme prévu. Ce n'est pas le cas pour Git ou Mercurial.

Je voudrais créer un script bash que je peux exécuter pour faire exactement cela, en parcourant des répertoires et l'un git pullou l' autre hg pull. Je n'ai tout simplement pas beaucoup d'expérience de script bash.

Bryan Veloso
la source
On pourrait préciser si vous voulez que les commandes soient exécutées de manière récursive (dans tous les sous-dossiers), la réponse de mj41 étant la seule réponse que j'ai essayée (à partir d'ici et sur d'autres sites SO).
r_alex_hall
* le fait avec un tweak que je mentionne dans un commentaire à ce sujet.
r_alex_hall

Réponses:

81
for dir in ~/projects/git/*; do (cd "$dir" && git pull); done
jtimberman
la source
2
Thnx ... mais je dois aussi capturer les erreurs. Comment puis-je le faire Je n'ai jamais fait de programmation shell auparavant.
Shashwat
23

Si vous en avez besoin pour être récursif:

find . -type d -name .git -exec sh -c "cd \"{}\"/../ && pwd && git pull" \;

Cela descendra dans tous les répertoires sous le répertoire actuel et effectuera un tirage git sur les sous-répertoires contenant un répertoire .git (vous pouvez le limiter -maxdepth).

En pause jusqu'à nouvel ordre.
la source
@thprivileges: intelligent!
pause jusqu'à nouvel ordre.
9
-execdirest beaucoup mieux ici:find . -type d -name .git -execdir sh -c "pwd && git pull" \;
daniel kullmann
Ceci est une meilleure réponse à mon avis subjectif ... A travaillé immédiatement pour moi .. Vive
Voke Ransom Anighoro
Contrairement à la question qui me liait ici, cette commande fonctionnait réellement. Merci.
user1445967
7

Si vous avez installé GNU Parallel http: // www.gnu.org/software/parallel/, vous pouvez le faire:

cd ~/projects/git/; ls | parallel 'cd {} && git pull'

Cela fonctionnera en parallèle, donc, si certaines connexions réseau des serveurs git sont lentes, cela peut accélérer les choses.

Regardez la vidéo d'introduction de GNU Parallel pour en savoir plus: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
la source
Peut-être faire ls */pour vous assurer que vous apportez une contribution cohérente à cd.
Joe Corneli
4

Cela devrait marcher

find . -maxdepth 1 -type d -name '.git' -exec sh -c 'cd "{}" && pwd && git pull' \;
mj41
la source
En supprimant l' -maxdepth 1indicateur, c'est la seule commande que j'ai trouvée dans beaucoup de recherches et d'essais qui exécute une commande de manière récursive (dans tous les sous-répertoires, pas seulement les répertoires d'un niveau inférieur).
r_alex_hall
0

Pour le faire récursif sans utiliser findmaisforloop

for dir in ~/projects/git/*/*/; do (cd "$dir" && git pull); done
Loretoparisi
la source