TheQuest2000
TheQuest2000

Reputation: 35

How to use a for loop to create folders in bash

I want to create a directory in which there is a bunch of text files using a for loop. Here is my code:

#!/bin/bash
echo "enter the nums: "
read num1 num2
for (( counter=0; counter<$num2; counter++ ))
do
if [ $num1 -lt 10 ] && [ $num2 -lt 10 ];
then
mkdir $num1 && touch $num1/$num1$num2.txt
echo "$num1""$num2" > $num1/$num1$num2.txt
else
echo "you weren't supposed to do that"
fi
done

What I want to happen if for example the user entered: "2 9"

Make a directory called 2 In it make text files called 290.txt, 291.txt, 292.txt... up till 299.txt.

Instead, what happens right now is it makes the directory and gives an error that the directory already exists. I don't know the next step, please help.

Upvotes: 0

Views: 1846

Answers (3)

Gordon Davisson
Gordon Davisson

Reputation: 125788

The biggest problem here is that you're doing things inside the loop that really only should be done once. Specifically, the error you're getting is because it tries to create the directory every time through the loop, but you can only create it once. Also, if the user enters too large a number, it'll print multiple error messages (e.g. if num2 is entered as 500, it'll print 500 error messages). You need to do both the error check and creating the directory once, before the loop.

A second problem is that you don't add $counter to the filename, so if the user enters "2 9", it'll create a file named 29.txt nine times.

You also have some more minor issues: in general, error messages should be printed to standard error instead of standard output (you can redirect them with >&2), and if there's an error the script should exit with a nonzero status. Also, you should (almost always) put double-quotes around variable references, to avoid weird results if the variables are blank or contain whitespace or some other things. You also don't need to touch files before writing into them (using > somefile will create the file if it doesn't exist).

With these things fixed (and some stylistic tweaks), here's what I get:

#!/bin/bash

echo "enter the nums: "
read num1 num2

if ! [ "$num1" -lt 10 ] || ! [ "$num2" -lt 10 ]; then
    echo "you weren't supposed to do that" >&2    # message send to stderr
    exit 1    # exit with error status
fi

mkdir "$num1" || exit $?    # if mkdir fails, exit with its error status

for (( counter=0; counter<$num2; counter++ )); do
    echo "${num1}${num2}" > "${num1}/${num1}${num2}${counter}.txt"
done

BTW, the ! [ "$num1" -lt 10 ] tests may look a little weird; why not just use [ "$num" -ge 10 ]? I did it that way in case $num1 and/or $num2 isn't a valid number, in which case both -lt and -ge tests would fail; using a negated test makes that an error rather than a success.

Upvotes: 1

Arash Khavari
Arash Khavari

Reputation: 19

Here you are! change the if and for statement parent and child:

#!/bin/bash
echo "enter the nums: "
read num1 num2
if [ $num1 -lt 10 ] && [ $num2 -lt 10 ]; then
  mkdir $num1
  for i in $(seq 0 $num2); do
    touch $num1/$num1$num2$i.txt
    echo "$num1""$num2""$i" > $num1/$num1$num2$i.txt
  done
else
  echo "you weren't supposed to do that"
fi

Upvotes: 1

Fellipe
Fellipe

Reputation: 42

I'm not fluent in bash or anything, but it looks like mkdir $num1 is called on every loop. Find out first if the directory exists.

Upvotes: 1

Related Questions