3

I have this code to check the status of all of my git folders.

find / -maxdepth 3 -not -path / -path '/[[:upper:]]*' -type d -name .git -not -path "*/Trash/*" -not -path "*/Temp/*" -not -path "*/opt/*" -print 2>/dev/null |
{
    while read gitFolder; do
        (
            parent=$(dirname $gitFolder);
            Status=$(git -C $parent status)
            if [[ $Status == *Changes* ]]; then
                echo $parent;
                git -C $parent status --porcelain
                echo ""
            elif [[ $Status == *ahead* ]]; then
                echo "Push $parent";
                echo
            elif [[ $Status == *diverged* ]]; then
                echo "Sync $parent";
                echo
            fi
        ) &
    done
    wait
}

When I run it sequentially, I get a nice readable print in the terminal. But the speed gets slower. When I run it in parallel (using &), I get a very good speed, but the output becomes a total mess.

Is it possible to lock the output for each inner shell somehow and print each inner shell's standard output in a block?

2
  • For each git directory only one of else condition will be executed, so why don't you merge bot echo command into one single echo command. Commented Sep 10, 2022 at 11:43
  • @Prvt_Yadav, that's one option. But I'm using a messaging script to show headers and details in different colors. I have not included that here. The real usage is Info "Push $parent"; Divide Commented Sep 10, 2022 at 11:59

1 Answer 1

4

GNU Parallel is built for exactly this:

doit() {
        gitFolder="$1"
        parent=$(dirname $gitFolder);
        Status=$(git -C $parent status)
        if [[ $Status == *Changes* ]]; then
            echo $parent;
            git -C $parent status --porcelain
            echo ""
        elif [[ $Status == *ahead* ]]; then
            echo "Push $parent";
            echo
        elif [[ $Status == *diverged* ]]; then
            echo "Sync $parent";
            echo
        fi
}
export -f doit
find / -maxdepth 3 -not -path / -path '/[[:upper:]]*' -type d -name .git -not -path "*/Trash/*" -not -path "*/Temp/*" -not -path "*/opt/*" -print 2>/dev/null |
  parallel -j0 doit

Grouping of output is done by default.

You can even let GNU Parallel compute $parent:

doit() {
        parent="$1"
        Status=$(git -C $parent status)
        :
}
... | parallel -j0 doit {//}
1
  • Such a beautiful answer and utility. Thank you so much. Works like a charm. Commented Sep 11, 2022 at 6:58

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.