find ~ -type d -name .git | sed 's?/\.git$??' | awk '{ print "-------------------------"; print "\033[1;32mGit Repo:\033[0m " $0; system("git --git-dir=\""$0"\"/.git --work-tree=\""$0"\" status")}'
To understand how this works, it's important to know that a Git work tree has a .git
subdirectory at its project root folder, containing metadata of Git.
With find ~ -name .git -type d
we find in the home directory of the current user ~
all the directories (-type d
) named .git
(-name .git
), which we expect to be the metadata folders of Git work trees.
We pipe the resulting list of .git
path names to Sed for further processing.
With sed 's?/\.git$??'
we remove the /.git
ending from the path.
We pipe the resulting list of .git
path names with the /.git
ending to Awk for further processing.
We print a header line with print "-------------------------"
.
Then we print "Git Repo:" in green, followed by the path of the work tree with print "\033[1;32mGit Repo:\033[0m " $0
. Note that the $0
variable in Awk holds the value of the entire current line, in this example the path of the work tree.
Then with system
we execute git status
in the work tree at $0
:
system("git --git-dir=\""$0"\"/.git --work-tree=\""$0"\" status")
It looks a bit horrible, but it has to, to be safe:
system
is a string.$0
inside the string.$0
in the middle of "some string"
, the correct way to write in Awk is "some " $0 " string"
. If the value of $0
is example
, then the value of the last expression becomes some example string
.$0
in double-quotes, so that the shell treats it as a single string value, and does not apply word splitting, which would break the command for example when the work tree contains spaces.cd "some path"
when the value of $0
is some path
, we would have to write "cd \"" $0 "\""
.For example if the work tree path is X
, then the above command will effectively run:
git --git-dir=X.git --work-tree=X status