LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Bash script to make directories recursive with depth and size (https://www.linuxquestions.org/questions/linux-newbie-8/bash-script-to-make-directories-recursive-with-depth-and-size-4175581835/)

genezing 06-09-2016 03:58 AM

Bash script to make directories recursive with depth and size
 
Hello,

I was wondering how one makes a bash script given a depth and a size/layer to make directories in directories and so on. For example I pass depth = 3 and size = 2 than the output needs to look like:

Code:

├── dir1
│** ├── dir3
│** │** └── dir7
│  │  └── dir8
│  ├── dir4
│  │  └── dir9
│  │  └── dir10
├── dir2
│  ├── dir5
│  │  └── dir11
│  │  └── dir12
│  ├── dir6
│  │  └── dir13
│  │  └── dir14

But I don't kow how I could program this recursive, my code that I have now is with static depth:

Code:

for (( g=1; g<=$size; g++ ))
do
for (( f=1; f<=$size; f++ ))
do
for (( e=1; e<=$size; e++ ))
do
for (( d=1; d<=$size; d++ ))
do
for (( c=1; c<=$size; c++ ))
do

mkdir -p foo/$g/$f/$e/$d
done
done
done
done
done

greetings

Turbocapitalist 06-09-2016 05:07 AM

If you're using bash you could use sequence expressions:

Code:

mkdir -p dir{1..2}/dir{3..6}/dir{7..14}/
That will give you 74 directories. They won't quite get the numbering you describe above, but is it close enough?

genezing 06-09-2016 05:15 AM

That is not really what I want, I want to use a variable depth, in your code the depth is 3, but I want a script where I can pass for example the depth as $1.

Turbocapitalist 06-09-2016 05:30 AM

Could you define your own bash function so that it can call itself recursively to create directories up to a certain depth?

genezing 06-09-2016 05:39 AM

Well I don't know, But if so it would look like something like this I guess:

Code:


recursivedir() {

for (( g=1; g<=$1; g++ ))

($2 somewhere here = depth)
make -p dir
recursivedir(xxxx)
make-p dir

}


jpollard 06-09-2016 05:49 AM

Just look at it differently... It is nothing but a two dimensional array, with dimensions of size, depth.

You are just sequentially indexing all elements in the array - so using an i,j index, two nested loops would visit each directory... The number given to the given directory is just i + j * size.

The name of the directory is just a counter used to count the creation of a directory...

No recursion required.

Turbocapitalist 06-09-2016 05:51 AM

Here is a basic recursion function.

Code:

a () {
        echo "$1";
        if [[ $1 -lt $2 ]]; then
                b=$(($1+1));
                a $b $2;
        else
                return;
        fi
}

Run it like this:

Code:

a 1 3
Edit: the array approach makes more sense

jpollard 06-09-2016 05:57 AM

No recursion is necessary.

Think of it as a two dimensional array, and that you are examining each (i,j) identified element. The name of the directory could just be a counter accumulating the number of elements visited. If you get clever, you can construct the path of directory names you want, then just use the -p option of mkdir to create the entire string (hint - use 1 offset index computations to the i,j conversion).

It actually sounds like a homework assignment...

genezing 06-09-2016 07:15 AM

Thank you for your answers but I don't understand it fully, first of all this is not homework, yes I am a student studying Apllied Informatics but in school we don't see any bash scripting unfortunately, this is for my own goal of learning bash and Linux. So you are saying I should use a 2d array but how am I going to make directory on each level with the 2d array?

Code:


size=2
depth=3

for ((i=1;i<=depth;i++)) do
    for ((j=1;j<=size;j++)) do
        mkdir -p --how do I put the depth here?--
    done
done


keefaz 06-09-2016 07:24 AM

Revised my function, deleted the original script by accident...:/
Code:

# args: depth size
function makeDirs() {
  depth=$1
  size=$2
  #prevSize=0
  index=0
  lastSize=$2
 
  declare -a 'dirs=(dir{'1..$2'})'
 
  while ((depth-- > 1)); do
    declare -a tmp=(${dirs[@]:$index})
    for d in ${tmp[@]}; do
      for ((i = 0; i < size; i++)); do
        dirs+=($d/dir$((++lastSize)))
      done
      ((index++))
    done
    #((prevSize += size))
  done
 
  mkdir "${dirs[@]}"
}

makeDirs 2 2

Edit, found a bug in logic, changed (and commented) prevSize with index

pan64 06-09-2016 07:25 AM

mkdir -p can create not only a single dir, but also its parent (recursively) - see man mkdir.
So you only need to generate the list of subdirs (of the given depth) and mkdir -p <list> will do it in one.


All times are GMT -5. The time now is 09:04 AM.