I have already read posts like How can I store the “find” command results as an array in Bash or Creating an array from a text file in Bash or Store output of command into the array
Now my issue is the following: How to do this in parallel?
Background:
I have a script for processing a large git repository with a lot of submodules and perform certain actions within these. Sometimes there are some tasks that take a while so meanwhile I want to give some user feedback to indicate that something is still happening and the code isn't just stuck ^^
I have a function
function ShowSpinner()
{
pid=$!
while [ -d /proc/$pid ]
do
for x in '-' '/' '|' '\\'
do
echo -ne ${x}" \r"
sleep 0.1
done
done
}
for displaying a little spinner while doing long tasks. And so far currently I use this e.g. like
while IFS= read -r line
do
# Some further processing of the output lines here
done <<< $(git pull 2>&1) & ShowSpinner
which works fine and always displays the spinner until the task is finished.
In particular I use this also for finding submodules in a git repository like
function FindSubmodules()
{
# find all .git FILES and write the result to the temporary file .submodules
find -name ".git" -type f > .submodules & ShowSpinner
# read in the temporary file
SUBMODULES=$(cat .submodules)
# and delete the temporary file
rm .submodules
}
later I iterate the submodules using e.g.
function DoSomethingWith()
{
for submodule in ${SUBMODULES}
do
echo $submodule
done
}
FindSubmodules
DoSomethingWith
Of course I do more stuff in there, this is only a short example.
This works find, but what I don't like here is that this file .submodules
is created (and if only temporary). I would prefer to directly store the result in an array and then iterate that one directly.
So after reading mentioned posts I tried to use something like simply
IFS=$'\n'
SUBMODULES=( $(find -name ".git" -type f)) & ShowSpinner
or from the links also
readarray SUBMODULES < <(find -name ".git" -type f) & ShowSpinner
or
readarray -t SUBMODULES "$(find -name ".git" -type f)" & ShowSpinner
and then iterate like
for submodule in ${SUBMODULES [@]}
do
echo $submodule
done
For all three options the result is basically the same: The spinner works fine but all that I get using this is one single entry with the last char of the ShowSpinner
instead of the results of find
. Without the & ShowSpinner
it works fine but of course doesn't show any feedback of a long tasks.
What am I doing wrong? How can I get the readarray
to work in parallel with the ShowSpinner
function?
Update as suggested I have put it to a function (actually I already had functions just didn't put the spinner behind the entire function so far)
function FindSubmodules()
{
echo ""
echo ${BOLD}"Scanning for Submodules ... "${NORMAL}
SUBMODULES=($(find -name ".git" -type f))
for submodule in "${SUBMODULES[@]}"
do
echo $submodule
done
}
function CheckAllReposForChanges()
{
# Check Submodules first
for submodule in "${SUBMODULES[@]}"
do
# remove prefixed '.'
local removedPrefix=${submodule#.}
# remove suffix '.git'
local removedSuffix=${removedPrefix%.git}
echo "${BASEPATH}${removedSuffix}"
done
# Check the main repo itself
echo "${BASEPATH}"
echo ""
}
FindSubmodules & ShowSpinner
CheckAllReposForChanges
the CheckRepoForChanges
function itself works just fine.
What I get now is the spinner and then the correct output from the first FindSubmodules
like e.g.
./SomeFolder/.git
./SomeOtherFolder/.git
./SomeThirdFolder/.git
etc
However when it comes to the CheckAllReposForChanges
(again the echo
is just an example for debugging) I don't get any output except the main repository path. It seems like now SUBMODULES
is empty since it is being filled in the background. It worked with the solution I used originally.