Reputation: 87
I'm trying to write a script that performs actions of files with different extensions. To make it as easy to add different actions as possible, the extensions are read from an array, files are found via the "find" command, and results returned to a dynamically generated array named after the file extension that was searched.
To add a new extension to search for I can simply add to the file_ext array.
I create the array like this:
file_exts=("dsd" "dsdd" "dmesg")
for ext in "${file_exts[@]}"
do
echo "Finding $ext files"
eval var="exts_$ext"
declare -a $var="($( find "$dirs_target" -name "*.$ext"))"
done
The arrays are created correctly, and I can manually echo "${exts_dsd[0]} ${exts_dsd[1]}" and see the entries, However, I can't find a way of looping through each entry in the dynamically assigned arrays.
I have tried a few combinations using eval, and I can print out the first entry in the array, IE just referencing "$exts_dsd" Here are two things I've already tried:
for varname in "${!exts_@}"
do
for entry in ${varname[@]}
do
echo "$varname : $entry"
done
eval value=\$${varname[@]}
echo "$varname=$value"
done
How can I loop through each entry in the above for loop, so I can print out all the entries in all the dynamically created arrays?
Here is a complete test script:
#! /bin/bash
file_exts=("dsd" "dsdd" "dmesg")
dirs_target="/tmp/arraytest/"
echo "Creating $dirs_target"
if [[ ! -d "$dirs_target" ]]; then
if ! mkdir "$dirs_target"; then
echo "Couldn't create temp dir"
exit 1
fi
fi
echo "Creating test files"
for tmpfile in $( seq 0 5 )
do
echo -e "\tCreating $dirs_target$tmpfile.dsd"
if ! touch "$dirs_target/$tmpfile.dsd"; then
echo "Coudn't create $dirs_target/test$tmpfile.dsd"
exit 1
fi
done
echo ""
echo "-----Finding Files-----"
for ext in "${file_exts[@]}"
do
echo "Finding $ext files"
eval var="exts_$ext"
declare -a $var="($( find "$dirs_target" -name "*.$ext"))"
done
echo ""
echo "-----File Extensions-----"
for varname in "${!exts_@}"
do
for entry in ${varname[@]}
do
echo "$varname : $entry"
done
eval value=\$${varname[@]}
#echo "$varname=$value"
done
echo ""
echo "Finishing."
rm -rf "$dirs_target"
Upvotes: 0
Views: 227
Reputation: 87
I've found the answer. I had the eval statement slightly wrong.
echo "-----File Extensions-----"
for varname in "${!exts_@}"
do
echo "varname=$varname"
eval testvalue="\${$varname[@]}"
for entry in $testvalue
do
echo -e "\tFile: $entry"
done
done
As a bonus, I've also figured out how to add to a dynamically created array
var="table_$entry"
declare -a $var
while read -r line
do
eval $var+=\(\'"$line"\'\)
done < "$dirs_table"
Upvotes: 0
Reputation: 241768
To loop over the entries, you have to use the same trick as when creating them: just store the variable name in a variable. The point is to include the [@]
index, too, which will be correctly recognized in the indirection:
for varname in "${!exts_@}" ; do
arr=$varname'[@]'
for entry in "${!arr}" ; do
echo "$varname : $entry"
done
done
Also note that eval
isn't needed in
# eval var="exts_$ext"
var=exts_$ext # works even better!
Upvotes: 2