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.
    – Prvt_Yadav
    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 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. Sep 11, 2022 at 6:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .