Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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/
share|improve this question
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. – Nanda 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

up vote 26 down vote accepted

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

share|improve this answer
Could I do for i in */; do mkdir "$i/itemone" "$i/itemtwo"; done for multiple, not-in-order directory names? – Nanda Jan 20 '13 at 15:36
I tested this and it is very much possible. Thanks. – Nanda Jan 20 '13 at 15:39
See my edited post – Gilles Quenot Jan 20 '13 at 15:42
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}
share|improve this answer

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

share|improve this answer
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
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.

share|improve this answer
+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}
share|improve this answer
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 Jan 21 '13 at 11:06

You can do that like that:

mkdir {a,b,c,d}/tmp1
share|improve this answer
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
share|improve this answer
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
Shouldn't that be if [ -d "$x" ];…? – kojiro Jan 20 '13 at 21:43
Yes. I practically never have spaces in filenames and tend to forget that stuff... – goldilocks Jan 21 '13 at 7:40

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
share|improve this answer
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

share|improve this answer

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?

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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