tl;dr:
- Change
for i in ls -d Module*; do
tofor i in Module*/;do
- Replace
for j in `grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx | grep "name"` ; do
echo $j
done
with
while IFS= read -r j; do
echo "$j"
done < <(grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" "$i/003.Design/003.Data.efx" | grep "name")
See below for a full discussion.
for i in ls -d Module*; do
will simply enumerate tokens ls
, -d
and (possibly expanded) Module*
instead of enumerating the output from an ls
command.
To correct that immediate problem, you'd have to use command substitution (for i in $(ls -d Module*; do)
), but that is not advisable, because using globbing (pathname expansion) directly is the robust, proper solution: for i in Module*/; do
Similarly, it's not advisable to use a for
loop to parse command output line by line, because the output is subject to word splitting, among other shell expansions.
Effectively, the for
loop enumerates whitespace-separated tokens rather than full lines.
Using a while
loop with IFS= read -r
, with input provided via process substitution, is the right approach - it ensures that lines are read unmodified.
Also, it's generally advisable to double-quote variable references to avoid unwanted shell expansions.
A revised form of your code is therefore:
shopt -s nullglob # ensure that a glob matching nothing expands to empty string
for i in Module*/; do
if [[ -f "$i/003.Design/003.Data.efx" ]]; then
if grep -qe "Module-0000/003.Design/005.Types/${1:0:1}/$1" "$i/003.Design/003.Data.efx"; then
echo "$i $i/003.Design/003.Data.efx"
while IFS= read -r j; do
echo "$j"
done < <(grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" "$i/003.Design/003.Data.efx" | grep "name")
fi
fi
done