1

Hello just a noob hobbyist here so this hopefully isn't too simple of a question.

I am trying to write a script that will let me generate the entire file structure for my media using only user inputs. I have everything working execept at line 20 where the 'mkdir Season{1..$user_input4} lives. I would like it to take the user input_4 and make 1 + that many directories but I feel I may be looking at this from the wrong perspective as it instead makes a subdirectory named Season{1..(prints the user input)}.

#!/bin/bash
file_created="Directory Created"
directory_number=0
echo "How many directories should be created?"
read user_input
while [ $directory_number -ne $user_input ]
do 
    echo "Enter Directory Name"
    read user_input2 
        mkdir $user_input2
    directory_number=$((directory_number + 1))
echo "Do you want to create Seasons? Y/N"
    read user_input3
    if [ $user_input3 == "Y" ]
    then
        echo "Enter number of seasons"
            read user_input4
        cd $user_input2/
        mkdir Season{1..$user_input4}
        cd ..
    else
    :
    fi
done

If anyone has any ideas they would be greatly appreciated. Thanks!

2 Answers2

3

It doesn’t work this way because:

The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, (…).
[man bash, highlighting added]

Brace expansion happens before the variable is expanded and can only see {1..$user_input4}, which of course is not valid.

Another possible problem: If $user_input4 happens to be very big and you thus get a very long list of directory names you may exceed the shell’s ARG_MAX limit, which will make the command fail. You can use seq to create the number sequence, printf to create a zero-delimited list of arguments and xargs to call mkdir as often as necessary to work around that. Of course it’s save to use with a smaller number of arguments as well, so that’s the way to go if you’re dealing with both an unknown number and nasty vicious users:

printf 'Season%s\0' $(seq 1 $user_input4) | xargs -0 mkdir

If you want the number sequence to end at $user_input4 + 1, just replace the variable with the arithmetic expression $((user_input4 + 1)), e.g.:

printf 'Season%s\0' $(seq 1 $((user_input4 + 1))) | xargs -0 mkdir
dessert
  • 39,982
  • Will make sure to consult the manual for this in the future. These have basically got me where I needed to be for this. Thanks! – clearmedium May 21 '19 at 21:43
  • What's nice about printf (aside from avoiding the ARG_MAX limit) is that you can include the prefix: printf 'Season%d\0' $(seq 1 $user_input4) – steeldriver May 21 '19 at 22:09
  • @steeldriver Oh my, I totally forgot that, thanks! – dessert May 22 '19 at 04:17
-1

To my knowledge, mkdir does not accept a range of directories, at least not in the format you are trying to use it. You are creating the seasons almost like an array. But you have to pass them one at a time with spaces between them if you want to create more than one directory with the mkdir command.

Since you are accepting a numeric value in user_input4, you could try counting down from the value of user_input4 until you reach zero using a while loop.

while [ $user_input4 -gt 0 ]
do
  mkdir Season${user_input4}
  let user_input4=${user_input4}-1
done

The loop will naturally stop when user_input4 equals zero. Or if you needed one more than the number, just use -ge (greater or equal to). The only catch with this method is that it will create the directories in reverse order. So if user_input4 is "3", then the order would be:

mkdir Season3
mkdir Season2
mkdir Season1
S. Nixon
  • 402