Mher Harutyunyan
Mher Harutyunyan

Reputation: 183

Bash script to iterate over directories and create subdirectory

I have the following code which creates an array and iterate over a directory and create a subdirectory under each of the element of an array.

#!/bin/bash
cd /var/www
dirs=$(find * -maxdepth 0 -type d)

for dir in "${dirs[@]}"; do
        echo $dir
        mkdir $dir/backups
done

While it echo's all the directories, it creates a directory only on the last element of the array. What can be the issue?

Upvotes: 0

Views: 2248

Answers (2)

codeforester
codeforester

Reputation: 43019

The issue the array initialization - change it to:

dirs=($(find * -maxdepth 0 -type d))

However, the above statement can be problematic if you have directories that have white spaces in them.

You can use a simple glob instead - it handles white spaces too:

cd /var/www
dirs=(*/)
for dir in "${dirs[@]}"; do
  : your code
done

Upvotes: 0

George Vasiliou
George Vasiliou

Reputation: 6345

If you are on bash 4.4 particularly , you can use the readarray feature like bellow. Also using -maxdepth 0 seems not a good option - you probably need to use -maxdepth 1.

#!/bin/bash
cd /var/www
readarray -t -d'' dirs < <$(find . -maxdepth 1 -type d -print0)

for dir in "${dirs[@]}"; do
        echo $dir
        mkdir $dir/backups
done

But in case you can do the whole thing just with find and mkdir -v (verbose):

$ find . -maxdepth 1 -type d -name 'a*'
./appsfiles

$ find . -maxdepth 1 -type d -name 'a*' -exec mkdir -v {}/backup \;
mkdir: created directory './appsfiles/backup'

Using mkdir -v you get verbose messages from mkdir and you can skip the echo.
If you need the echo anyway, you can do it like:

$ find . -maxdepth 1 -type d -name 'a*' -exec bash -c 'echo $0 && mkdir -v $0/backup' {} \;
./appsfiles
mkdir: created directory './appsfiles/backup'

Upvotes: 1

Related Questions