Skip to main content
Code Review

Return to Answer

replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

Credits to this SO answer this SO answer and this blog post for pieces of this answer.

Credits to this SO answer and this blog post for pieces of this answer.

Credits to this SO answer and this blog post for pieces of this answer.

added 2314 characters in body
Source Link
Wildcard
  • 343
  • 3
  • 10

This works based on the fact that all valid git repositories contain a directory titled .git. The -execdir flag to find makes the given command run within the directory that contains the found file. So, what this command does is:

find . # find recursively, starting in the current directory...
-type d # ...files of type "directory"...
-name '.git' # ...whose name is '.git'...
-print # ...then, for each file found, print the name of the file (the dir) you found, and...
-execdir git status \; # ...from the directory containing that .git dir, run 'git status', and...
-exec echo \; # ...finally 'echo' to insert a blank line in the output for readability.

This is great for any git commands you need to run. Unfortunately, because it depends on the presence of the .git directory to establish which subdirs to run in, it's non trivial to extend it to run arbitrary commands.

In other words, it doesn't actually "run the command recursively in all subdirs until it finds one that works", as requested in the question post. Instead, it uses the presence of a specific file (in this case a .git dir) to establish which subdirs to run in, and then runs the command only in those specific dirs.

I have never used hg, but from a quick google search it appears that hg repos are similar to git repos and contain a .hg directory in each valid repo. So this command could probably work for hg commands also. Just replace .git with .hg and git status with the hg command you want to run.

So if there is a single file or directory whose presence will guarantee you want to run the command (and that it will succeed) and whose absence will guarantee that you don't want to run the command (i.e. that the command will fail), then you can use that file's presence or absence as a proxy for checking the exit status of the command, and that is what I am doing with find. I hope that's clear enough.

Looking at your filecheck.sh example, I see that it does have such a file which can be used as a proxy as described above: ok.txt. So the command would be something like:

find . -name 'ok.txt' -print -execdir /full/path/to/filecheck.sh \; -exec echo \;

I hope this helps.

This works based on the fact that all valid git repositories contain a directory titled .git. The -execdir flag to find makes the given command run within the directory that contains the found file. So, what this command does is:

find . # find recursively, starting in the current directory...
-type d # ...files of type "directory"...
-name '.git' # ...whose name is '.git'...
-print # ...then, for each file found, print the name of the file (the dir) you found, and...
-execdir git status \; # ...from the directory containing that .git dir, run 'git status', and...
-exec echo \; # ...finally 'echo' to insert a blank line in the output for readability.

This is great for any git commands you need to run. Unfortunately, because it depends on the presence of the .git directory to establish which subdirs to run in, it's non trivial to extend it to run arbitrary commands.

In other words, it doesn't actually "run the command recursively in all subdirs until it finds one that works", as requested in the question post. Instead, it uses the presence of a specific file (in this case a .git dir) to establish which subdirs to run in, and then runs the command only in those specific dirs.

I have never used hg, but from a quick google search it appears that hg repos are similar to git repos and contain a .hg directory in each valid repo. So this command could probably work for hg commands also. Just replace .git with .hg and git status with the hg command you want to run.

So if there is a single file or directory whose presence will guarantee you want to run the command (and that it will succeed) and whose absence will guarantee that you don't want to run the command (i.e. that the command will fail), then you can use that file's presence or absence as a proxy for checking the exit status of the command, and that is what I am doing with find. I hope that's clear enough.

Looking at your filecheck.sh example, I see that it does have such a file which can be used as a proxy as described above: ok.txt. So the command would be something like:

find . -name 'ok.txt' -print -execdir /full/path/to/filecheck.sh \; -exec echo \;

I hope this helps.

Source Link
Wildcard
  • 343
  • 3
  • 10

It looks like all your repos are only two levels deep. If that is the case, you might try:

for i in */* ; do [ -d "$i" ] && git --git-dir="$i"/.git --work-tree="$i" status 2>/dev/null && echo "$i" && echo ; done

Credits to this SO answer and this blog post for pieces of this answer.

EDIT: Even simpler, by adapting 200_success's answer:

find . -type d -name '.git' -print -execdir git status \; -exec echo \;
lang-bash

AltStyle によって変換されたページ (->オリジナル) /