The issue is that the wait
is run by the wrong shell process. In bash
, each part of a pipeline is running in a separate subshell. The background tasks belong to the subshell executing the while
loop. Moving the wait
into that subshell would make it work as expected:
find ... |
{
while ...; do
...
( git -C ... && ... ) &
done
wait
}
echo 'done.'
You also have some unquoted variables.
I would get rid of the pipe entirely and instead run the loop from find
directly, which gets rid of the need to parse the output from find
.
find / -type d -name .git \
! -path '*/Temp/*' \
! -path '*/opt/*' \
! -path '*/Trash/*' \
-exec sh -c '
for gitpath do
git -C "$gitpath"/.. pull &
done
wait' sh {} +
Or, using -prune
to avoid even entering any of the subdirectories we don't want to deal with,
find / \( -name Temp -o -name Trash -o -name opt \) -prune -o \
-type d -name .git -exec sh -c '
for gitpath do
git -C "$gitpath"/.. pull &
done
wait' sh {} +
As mentioned in comments, you could also use xargs
to have greater control over the number of concurrently running git
processes. The -P
option (for specifying the number of concurrent tasks) used below is non-standard, as are -0
(for reading \0
-delimited pathnames) and -r
(for avoiding running the command when there's no input). GNU xargs
and some other implementations of this utility have these options though. Also, the -print0
predicate of find
(to output \0
-delimited pathnames) is non-standard, but commonly implemented.
find / \( -name Temp -o -name Trash -o -name opt \) -prune -o \
-type d -name .git -print0 |
xargs -t -0r -P 4 -I {} git -C {}/.. pull
I'm sure GNU parallel
could also be used in a similar way, but since this is not the main focus of this question I'm not pursuing that train of thought.
read
. Usingfind … |
is practically newer a good way of dealing with these things. Also, it feels very awkward that instead of specifying the directories you actually want to search in you exclude some. Congratulations for searching/sys/
and/dev/
and/var/run/
… for git repos! – Marcus Müller Jan 27 '22 at 17:32wait
in the same subshell helps. – Kusalananda Jan 27 '22 at 17:41/
, which really makes no sense). – Marcus Müller Jan 27 '22 at 17:46read line
, if you do that, you probably wantIFS= read -r line
instead, see Understanding "IFS= read -r line". (Still only matters if your filenames are naughty.) – ilkkachu Jan 28 '22 at 12:46