GP89
GP89

Reputation: 6730

Bash script, array not getting created as expected

I'm pretty new to bash scripting and I'm obviously missing some fairly basic understanding as I can't work out why this script isn't doing as I'd expect. I've made a simple example reproducing the problem, it is supposed to make 3 folders, with 3 folders inside, then touch a file test inside of each.

Here's the script:

#!/bin/sh
DIR_LEVEL_1=("1" "2" "3")
for DIR_1 in ${DIR_LEVEL_1[@]}; do
  mkdir $DIR_1
  DIR_LEVEL_2=("$DIR_1/a" "$DIR_1/b" "$DIR_1/c")
  echo $DIR_LEVEL_2
  for DIR_2 in ${DIR_LEVEL2[@]}; do
    mkdir $DIR_2
    touch "$DIR_2/test"
  done
done

The problem I was having was the it wasn't entering the second for loop, I put in that echo and it looks like the second array isn't being created properly as the output of the script is:

1/a
2/a
3/a

which is just the first element of the array.

running with -xv flag I get this, which shows it's taking no notice of that nested for loop (I guess because the array didn't get created as I wanted?)

#!/bin/sh
DIR_LEVEL_1=("1" "2" "3")
+ DIR_LEVEL_1=("1" "2" "3")
for DIR_1 in ${DIR_LEVEL_1[@]}; do
  mkdir $DIR_1
  DIR_LEVEL_2=("$DIR_1/a" "$DIR_1/b" "$DIR_1/c")
  echo $DIR_LEVEL_2
  for DIR_2 in ${DIR_LEVEL2[@]}; do
    mkdir $DIR_2
    touch "$DIR_2/test"
  done
done
+ for DIR_1 in '${DIR_LEVEL_1[@]}'
+ mkdir 1
+ DIR_LEVEL_2=("$DIR_1/a" "$DIR_1/b" "$DIR_1/c")
+ echo 1/a
1/a
+ for DIR_1 in '${DIR_LEVEL_1[@]}'
+ mkdir 2
+ DIR_LEVEL_2=("$DIR_1/a" "$DIR_1/b" "$DIR_1/c")
+ echo 2/a
2/a
+ for DIR_1 in '${DIR_LEVEL_1[@]}'
+ mkdir 3
+ DIR_LEVEL_2=("$DIR_1/a" "$DIR_1/b" "$DIR_1/c")
+ echo 3/a
3/a

So it only creates the first level of folders

Upvotes: 4

Views: 323

Answers (2)

camh
camh

Reputation: 42468

You have three problems here:

  1. The script should start with #!/bin/bash if you want to use bash, not #!/bin/sh
  2. echo $ARRAY will output only the first element of the array, not the whole array, which is why it looks like it is doing only the first element - it is not, but it is just printing the first. Use echo ${ARRAY[@]} to output the whole array.
  3. When you are iterating the second array, you have the variable name wrong. Your array is DIR_LEVEL_2, but you are iterating ${DIR_LEVEL2[@]}, which is empty (hence no iteration). You are missing an underscore before the 2

Upvotes: 4

kojiro
kojiro

Reputation: 77107

Well, the real issue with your script is that you create DIR_LEVEL_2, but you iterate over DIR_LEVEL2. (Note the underscore difference). However, you also neglect to quote "${array[@]}", which means it will not wordsplit properly. All that aside, might I suggest you use brace expansion to make this entire thing a better experience?

#!/bin/bash

dirs=( {1,2,3}/{a,b,c} )
mkdir -p "${dirs[@]}"
for d in "${dirs[@]}"; do
    touch "$d/test"
done

Edit/postscript: I notice your script above uses #!/bin/sh, but you've tagged this post bash. They are not the same thing. Unless you're certain you want to trade the greater featureset of bash for the greater portability of sh, use #!/bin/bash.

Upvotes: 3

Related Questions