creating a directory tree

Hi all,

I'd like to create a directory tree, and define from stdin how many levels deep and how many directories in each level should be created.
What I wrote does not work properly:

#!/bin/bash
#set -x

read -p " What root directory? " rootDir
[ -d $rootDir ] && { /bin/rm -R $rootDir; mkdir $rootDir; } || mkdir $rootDir
read -p " How many directories? " dirnb
read -p " How many levels? " levnb

l=0
generate() {
   ((l++))
   for (( n=0; n < ${dirnb:-1}; n++ )); do
      mkdir $1/directory$n
   done
   while [ $l -lt ${levnb:-1} ]; do
      for directory in $1/*; do
         generate $directory
      done
   done
}
generate $rootDir
find $rootDir

the result is:

 What root directory? testwx
 How many directories? 2
 How many levels? 3
testwx
testwx/directory1
testwx/directory1/directory1
testwx/directory1/directory0
testwx/directory0
testwx/directory0/directory1
testwx/directory0/directory1/directory1
testwx/directory0/directory1/directory0
testwx/directory0/directory0
testwx/directory0/directory0/directory1
testwx/directory0/directory0/directory0

I should get

testwx
testwx/directory1
testwx/directory1/directory1
testwx/directory1/directory1/directory1
testwx/directory0/directory1/directory0
testwx/directory1/directory0
testwx/directory1/directory0/directory1
 testwx/directory0/directory1/directory0
testwx/directory0
testwx/directory0/directory1
testwx/directory0/directory1/directory1
testwx/directory0/directory1/directory0
testwx/directory0/directory0
testwx/directory0/directory0/directory1
testwx/directory0/directory0/directory0

What am I missing?

Thanks in advance

PS: it's not homework!

Hi NBaH,

When cooking something recursive I think there are two essential ingredients:

  • local variables ( "typeset var" )
  • variable passing

There are multiple functions active at the same time and their variables should not interfere with parent's variables. To make a distinction between local and global variables I used lower case and upper case. Also there was a while loop in the generate function that should be an if statement.

#!/bin/bash
#set -x

read -p " What root directory? " ROOTDIR
[ -d $ROOTDIR ] && { /bin/rm -R $ROOTDIR; mkdir $ROOTDIR; } || mkdir $ROOTDIR
read -p " How many directories? " DIRNB
read -p " How many levels? " LEVNB

generate() {
   typeset path=$1
   typeset level=$2
   typeset directory
   typeset n
   ((level++))
   for (( n=0; n < ${DIRNB:-1}; n++ )); do
      mkdir $path/directory$n
   done
   if [ $level -lt ${LEVNB:-1} ]; then
      for directory in $path/*; do
         generate $directory $level
      done
   fi
}
LEVEL=0
generate $ROOTDIR $LEVEL
find $ROOTDIR

---------- Post updated at 11:10 PM ---------- Previous update was at 10:33 PM ----------

Also, if you move the creation of the topdir at each level to the function, you can make it a bit shorter:

#!/bin/bash

read -p " What root directory?     " ROOTDIR
read -p " How many subdirectories? " SUBDIRS
read -p " How many levels?         " LEVELS
if [ -d $ROOTDIR ]; then
  echo $ROOTDIR exist
  exit 1
fi

generate() {
   typeset path=$1
   typeset level=$2
   typeset n
   mkdir $path
   if (( level > 0 )); then
     for (( n=0; n < SUBDIRS; n++ )); do
        generate $path/directory$n $((level-1))
     done
   fi
}

generate $ROOTDIR $LEVELS
find $ROOTDIR

Hi Scrutinizer,

help typeset says it's obsolete, and to use declare instead.
As you pointed to the differences between global and local variables, I finally used local builtin, which seems to be more appropriate in this case, isn't it.

I thank you very much.