The non-eval
solution here is to use an array.
subdirs=( subdir{1..5}/subdir{1..5}/subdir{1..5}/subdir{1..5} )
mkdir -p "${subdirs[@]}"
This is a case of BashFAQ/050 - I'm trying to put a command in a variable, but the complex cases always fail! Syntax parsing, which handles things like Brace Expansion, comes before Parameter Expansion when bash evaluates the command line, so syntax characters inside of variables are going to be treated as literal data with no special meaning.
If you can't use this approach because the expansion isn't hardcoded for whatever reason, you can run a recursive function that doesn't rely on eval
to do the work.
_f_mkdirs() {
basename=$1
levels=$2
subdirs=$3
# check the recursive exit condition
if (( levels > 0 )) ; then
# make however many directories at this level that you want
for ((i=1 ; i <= subdirs ; i++)) ; do
newdir="${basename}${i}"
mkdir "${newdir}"
# change into each directory and repeat the process until
# you've descended to all levels
# runs in a subshell to preserve current working state
( cd "${newdir}" && _f_mkdirs "${basename}" "$((levels-1))" "${subdirs}" )
done
fi
}
# to replicate your sample structure, call with: _f_mkdirs subdir 4 5