Looping Through Subdirectories and Running a Command in Each

48

28

I have a set of repositories sorted into directories based on their VCS (Git, Mercurial, SVN). With Subversion I was able to run svn update * in the parent directory and it would loop through each directory and update each repository as expected. That's not the case for Git or Mercurial.

I would like to come up with a bash script that I can run to do exactly that, loop through directories and either git pull or hg pull in each. I just don't have much bash scripting experience.

Bryan Veloso

Posted 2009-09-21T21:34:05.153

Reputation: 583

It could be clarified whether you want the commands executed recursively (in all subfolders), where mj41's answer is the only one I've tried (from here and at other SO sites) that does that. – r_alex_hall – 2019-11-08T01:48:46.213

>

  • does that with a tweak that I mention in a comment on it.
  • < – r_alex_hall – 2019-11-08T01:54:12.880

    Answers

    85

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

    jtimberman

    Posted 2009-09-21T21:34:05.153

    Reputation: 20 109

    2Thnx... but i need to capture errors as well. How can I do so. I've never done shell programming before. – shashwat – 2015-02-16T10:37:47.627

    If I remove parenthesis it stops working. What's the concept behind it? – Mohit Kumar – 2019-12-17T06:28:09.883

    23

    If you need it to be recursive:

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

    This will descend into all the directories under the current one, and perform a git pull on those subdirectories that have a .git directory (you can limit it with -maxdepth).

    Paused until further notice.

    Posted 2009-09-21T21:34:05.153

    Reputation: 86 075

    This is a better answer in my subjective opinion... Worked immediately for me.. Cheers – Voke Ransom Anighoro – 2015-06-10T14:30:38.820

    Unlike the question that linked me here, this command actually worked. Thank you. – user1445967 – 2019-05-02T19:47:46.077

    @thprivileges: clever! – Paused until further notice. – 2012-01-06T21:41:52.013

    9-execdir is much better here: find . -type d -name .git -execdir sh -c "pwd && git pull" \; – daniel kullmann – 2012-01-09T07:51:19.530

    7

    If you have GNU Parallel http:// www.gnu.org/software/parallel/ installed you can do this:

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

    This will run in parallel so if some of the git servers' network connection are slow this may speed up things.

    Watch the intro video for GNU Parallel to learn more: http://www.youtube.com/watch?v=OpaiGYxkSuQ

    Ole Tange

    Posted 2009-09-21T21:34:05.153

    Reputation: 3 034

    Maybe do ls */ to be sure you're giving coherent input to cd. – Joe Corneli – 2018-03-10T19:17:57.503

    4

    This should work

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

    mj41

    Posted 2009-09-21T21:34:05.153

    Reputation: 141

    removing the -maxdepth 1 flag, this is the only command I've found in a lot of searching and trying that executes a command recursively (in all subdirectories, not just the directories one level down). – r_alex_hall – 2019-11-08T01:46:24.603

    2

    To do it recursive without using find but forloop

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

    loretoparisi

    Posted 2009-09-21T21:34:05.153

    Reputation: 151