1

i'm learning bash on linux, i found script for "while loop reading from a file" and modified a bit as below, i 'm trying to read a list file containing all the git repos, and i wanted to iterate all those git repos and run git status for all of them:

while read line; 
    do  echo $line;
        cd $line;
        git status;
done < repo.list

this part works fine, i can see status of each repo in stdout, but when i tried to write output to another file, it doesn't work:

while read line; 
    do  echo $line;
        cd $line;
        git status;
done < repo.list
> status.txt

how can i consolidate all git status output and write to a file? thanks!

1
  • i'm new to this, can this be done without loop? i googled a bit and found this find mydir -name .git -type d , i write this to repo.list file – jerry Mar 4 at 10:51
3

i googled a bit and found this find mydir -name .git -type d

You could do something like this, maybe:

find . -name '.git' -type d -print -execdir git status \;

That would look for directories called .git, then for each, print the path to it, and go to the containing directory and run git status there. (find -exec would run the command in the original directory, -execdir goes to where the matching file/directory was.)

You get output like

./this-stuff/.git
On branch master
Your branch is up to date with 'origin/master'.

and it would need some more trickery to post-process the .git out of it. (E.g. -exec sh -c 'echo "${1%.git}"' sh {} \; instead of the -print.)

In general, find may work if you want to do something on all files/directories in some subtree, matching some condition that is evident from the metadata of the files. But if you have an existing list, a shell loop is as good a way as any to process it.

4
  • 1
    -printf '%h\n' would do the trick with GNU find. – Stephen Kitt Mar 4 at 11:10
  • This answer doesn't show how to redirect the output, which is what the question is about. – Barmar Mar 4 at 17:10
  • @Barmar, You are absolutely correct. The answer says exactly nothing at all about redirections. – ilkkachu Mar 4 at 17:11
  • wow, thanks a lot, i'm learning new stuff, i didn't know this could be done with 1 line of command, i added > status.txt, it output paths and status of all git reps – jerry Mar 5 at 2:47
4

With the redirection on a new line, it applies to the empty command; to fix this, place it on the done line:

while IFS= read -r line; 
    do  echo "$line"
        (cd "$line"; git status)
done < repo.list > status.txt

See also Understanding IFS and Understanding "IFS= read -r line" and the linked questions for information on subtleties affecting read.

Using a subshell for the cd and git status together means that the changing directories won’t affect subsequent iterations of the loop, or even the shell running the while.

4
  • thanks a lot! it works for me – jerry Mar 4 at 10:31
  • That cd looks slightly suspect, would this only work if all the paths in the file are absolute? – ilkkachu Mar 4 at 10:57
  • btw, i didn't use IFS, i just change the "done" part, it also works, done < repo.list > status.txt – jerry Mar 4 at 11:03
  • Good point @ilkkachu, fixed. – Stephen Kitt Mar 4 at 11:07
1

Your issue is a simple typo as explained by Stephen already.

The task of running git status in each directory given by the line in a file could be done using xargs as well:

xargs -I {} git -C {} status <repo.list >status.txt

This calls git -C {} status for each line in the file repo.list. The {} will be replaced by the line read from the file, and the -C option to git will make the utility use an alternative directory for the status sub-command in place of the current one.

To have the repository path outputted before each call to git status, call a sh -c script:

xargs -I {} sh -c 'printf "REPOSITORY: %s\n" "$1"; git -C "$1" status' sh {} <repo.list >status.txt

Inside the sh -c script, the repository pathname is given by "$1".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.