I am trying to create a number of directories and subdirectories in one single command (ie avoiding for loops) like so:
mkdir -p {20..30}/{1..5}
This works no problem, and creates 10 directories, and inside each of them, it creates another 5. All good.
However I'd like to replace the subdirectories with an array, but this doesn't work as I expect.
For example, if I create:
tru=(1 2 3 4 5)
and do:
mkdir -p {20..30}/${tru[@]}
this is interpreted as
mkdir -p {20..30}/1 2 3 4 5
and only one subdirectory is created with name "1".
How can I make mkdir interpret my new array in a similar way to how it's doing with {1..5}?
The working example you have there with mkdir -p {20..30}/{1..5}
is a brace expansion. Implicit in the text produced by the shell expansion is a looping like behavior:
$ printf "mkdir -p %s\n" {1..3}/{10..12}
mkdir -p 1/10
mkdir -p 1/11
mkdir -p 1/12
mkdir -p 2/10
mkdir -p 2/11
mkdir -p 2/12
mkdir -p 3/10
mkdir -p 3/11
mkdir -p 3/12
The array expansion from ${array[@]}
is something different:
$ arr=(10 11 12 13)
$ printf "mkdir -p %s\n" {1..3}/${arr[@]}
mkdir -p 1/10
mkdir -p 2/10
mkdir -p 3/10
mkdir -p 11
mkdir -p 12
mkdir -p 13
So the only way to get what you want (in Bash) is with an explicit loop.
If, for some reason, you need the same order in the cartesian product of the brace expansion, you need two loops:
for outer in {10..20}; do
for inner in "${tru[@]}"; do
mkdir -p "$outer/$inner"
done
done
If you don't mind the order being different, you can do it in a single line:
$ for t in "${tru[@]}"; do mkdir -p {10..20}/"$t"; done
This loops through the outer first before the inner so the order is a little different. In this case, it does not matter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With