1

I'm trying to create a directory with list of directories with list of files. Could you explain me, why this script doesn't work properly?

createapp() {
    local folders=('graphql' 'migrations' 'models' 'tests')
    local files=('__init__.py' 'admin.py' 'apps.py' 'views.py')

    cd backend/apps
    mkdir $COMMAND2
    cd $COMMAND2

    for folder in $folders
        do mkdir $folder && cd $folder
        for file in $files
            do touch $file && cd ..
        done
    done
}

It creates a graphql directory, and an __init__.py file in it, but that's all.

6
  • 2
    for folder in $folders does not iterate over the array. Commented Jun 2, 2020 at 18:49
  • 4
    You want for directory in "${folders[@]}" Commented Jun 2, 2020 at 18:49
  • 1
    You don't really need the cd command. After mkdir "$folder", just do touch "$folder/$file". Right now, you are executing cd .. too soon: you want to do that after the file loop completes. Commented Jun 2, 2020 at 18:55
  • @chepner thank you Commented Jun 2, 2020 at 19:03
  • @WilliamPursell and you also <3 Commented Jun 2, 2020 at 19:03

2 Answers 2

2

There are a few problems:

  1. You aren't iterating over the contents of the array, only the first element.
  2. You are executing cd .. too soon; you want to do that after the loop that creates each file.

for folder in "${folders[@]}"; do
  mkdir -p "$folder" &&
  cd "$folder" &&
  for file in "${files[@]}"; do
    touch "$file"
  done && 
  cd ..
done

There are two ways to simplify this. If you keep the cd command, you only need one call to touch:

for folder in "${folders[@]}"; do
  mkdir -p "$folder" && cd "$folder" && touch "${files[@]}" && cd ..
done

Or you can get rid of the cd command, and pass a longer path to touch:

for folder in "${folders[@]}"; do
  mkdir -p "$folder" &&
  for file in "${files[@]}"; do
    touch "$folder/$file"
  done
done

or even

for folder in "${folders[@]}"; do
  mkdir -p "$folder" &&
  touch "${files[@]/#/$folder/}"
done
Sign up to request clarification or add additional context in comments.

Comments

0

If you want to get fancy, you can do all of this with zero loops and a combination of brace and array expansions:

#!/bin/bash

createapp() {
    local folders=('graphql' 'migrations' 'models' 'tests')
    local files=('__init__.py' 'admin.py' 'apps.py' 'views.py')

    IFS=,
    eval mkdir -p "{${folders[*]}}"
    eval touch "{${folders[*]}}/{${files[*]}}"
}

Note that the use of eval can be dangerous, but it's pretty limited in this implementation as the two arrays are local and not using user-defined input. If this was , you could embed brace and array expansion without the need for eval

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.