Suppose I have a directory structure like this:

$ [~/practice] ls
a/ b/ c/ d/

Now I want to create a directory tmp1 in all sub directories of practice and I do this:

$ [~/practice] mkdir */tmp1
mkdir: cannot create directory `*/tmp1': No such file or directory

Then I try the -p switch and I endup with a directory named * with a sub directory tmp1

$ [~/practice] mkdir -p */tmp1

$ [~/practice] ls
*/ a/ b/ c/ d/

I know the use of -p switch is to create multiple nonexistent directories. I just thought it might help.

How do I create tmp1 in all subdirectories at once?

If this can be done, how do I extend it to create \tmp1, \tmp2, \tmp3 in \a, \b and \c at once?

Edit: I missed mentioning that the directories don't have to be simple and in order, like a, b, c etc., and the directory to be created is not necessarily like tmp1, tmp2.

$ [~/practice] ls
dog/ cat/ rat/

In them, I would like to have something like

$ [~/practice] ls *
red/ blue/

red/ blue/

red/ blue/
  • 1
    Given Christopher's answer, you should clarify whether "create \tmp1, \tmp2, \tmp3 in \a, \b and \c" should result a total of 3 or 9 subdirectories. – manatwork Jan 20 '13 at 15:24
  • @manatwork: That's a good point. It should create 9 subdirectories. – Animesh Jan 20 '13 at 15:27
  • This my help to solve the space issue in the name of the directory sudo find ./ -depth -type d -exec echo '"{}/RCS"' \; – user114674 May 8 '15 at 15:16

10 Answers 10


With globs :

for dir in */; do mkdir -- "$dir/tmp1"; done


  • I treat only dirs (including symlinks to dirs) with the little hack of using */ as a glob
  • If you want to create multiple subdirs at once :

    for dir in */; do mkdir -- "$dir"/{tmp1,foo,bar,qux}; done

  • Could I do for i in */; do mkdir "$i/itemone" "$i/itemtwo"; done for multiple, not-in-order directory names? – Animesh Jan 20 '13 at 15:36
  • I tested this and it is very much possible. Thanks. – Animesh Jan 20 '13 at 15:39
  • See my edited post – Gilles Quenot Jan 20 '13 at 15:42
  • 1
    Brace expansion is not performed in quoted string. – manatwork Jan 20 '13 at 16:13
  • Yes, thanks, post edited by Stephane Chazelas accordingly... – Gilles Quenot Jan 20 '13 at 22:11

[...] how do I extend it to create \tmp1, \tmp2, \tmp3 in \a, \b and \c at once?

 mkdir {a,b,c}/tmp{1,2,3}

With GNU or BSD* find:

find -mindepth 1 -maxdepth 1 -type d -exec mkdir {}/newdir \;

or using parameter expansion:

mkdir -- "${dirs[@]/%/newdir}"

*Includes OS X

  • 2
    With standard find syntax: find . -name . -o -prune -type d -exec sh -c 'exec mkdir "$1/newdir"' sh {} \; – Stéphane Chazelas Jan 20 '13 at 22:04
  • 1
    Also note the differences between the two solutions: the first one includes hidden directories, the second one will add a newdir in the directories linked by any symlink in the current directory. – Stéphane Chazelas Jan 20 '13 at 22:06

Off topic since you're mentioning bash, but for the record, with zsh, you'd do:

mkdir -- $^dirs/tmp1

$^var turns on brace-like expansion for the expansion of the array. It's reminiscent of rc's ^ operator and in rc (or its derivative es), you'd write it:

mkdir -- $dirs^tmp1

However note (and the same applies to the bash solutions given here) that in the rc solution dirs would also contain symbolic links to directories. In the zsh solution, change *(/) to *(-/) if you want to include symlinks to directories.

  • +1 for your point about symlinks! This behavior may be desired, but mkdir's complaint about creating a duplicate directory can be suppressed with the -p flag. – kojiro Jan 20 '13 at 21:46

Portably, loop over the parent directories:

for d in */; do mkdir "$d/red" "$d/blue"; done

Add -- after mkdir if you may have directories whose name starts with -.

In zsh, you can do it in a single command with the e glob qualifier:

mkdir *(/e\''REPLY=($REPLY/{red,blue})'\')

but it's quicker to type this as two commands:

d=(*(/)); mkdir $^d/{red,blue}
  • 1
    On a site that is meant to be a reference, I'd rather say "mkdir -- whatever, and omit -- if you intend for the expansion of whatever to be possibly taken as options to the mkdir command.". There's no point in omiting -- here. It may not be a problem in the OP's case, but it is one in the general case. I think we have a duty to teach the correct and safe syntax here. – Stéphane Chazelas Jan 21 '13 at 10:35
  • @StephaneChazelas In a scripting context, I always put all necessary -- and quotes and big fat warnings when newlines aren't supported. In a command line context, I prefer to show the quick version that works in practice first, and the bulletproof version as a complement. – Gilles 'SO- stop being evil' Jan 21 '13 at 11:06

You can do that like that:

mkdir {a,b,c,d}/tmp1
  • 1
    What if he has 100 directories? – Bernhard Jan 20 '13 at 20:13

Variation on sputnick's answer which avoids non-directory files:

for x in *; do if [ -d "$x" ]; then mkdir "$x/tmp1"; fi; done
  • I treat only dirs, that"s all the magic... – Gilles Quenot Jan 20 '13 at 15:40
  • cool, got it ;) – goldilocks Jan 20 '13 at 15:44

This is a good one from the old Unix Masters (tested on FreeBSD 10.1) if you want to version control (with RCS check in locked: ci -l with a brief comment as ir: for initial release) your /etc/* config files on ~/.his/etc

sudo rsync -av /etc/ ~/.his
sudo find -d ~/.his/etc -type d -exec echo '{}/RCS' \; | xargs sudo mkdir -p
sudo find -d ~/.his/etc \! -name "RCS" | xargs sudo ci -l -mir -t-ir
  • I fail to see how this answer the OP – Archemar Mar 28 '15 at 7:07

Should be \! name "RCS" and it works best on the first check in.

sudo find ~/.his/etc \! -name "RCS" -ls

sudo find -d ~/.his/etc \! -name "RCS" | xargs sudo ci -l -mir -t-ir

This last one also works very well for the cjeck in part filtering all RCS content on the file name:

sudo find -d ~/.his/etc -type f | grep -v RCS | xargs sudo ci -l -mir -t-ir


this is a great help to me. i had a need to create a set of subdirectories in multiple folders and something like:


cd /dest/cont

for dir in */*/; do
    mkdir -p -- $dir/{FB,Video,Audio,proj};

worked great except when a white space is encountered. is there a way to ignore spaces in the */*/ part of the arguments?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.