# create multiple subdirectories



## andrewm659 (Mar 9, 2021)

I am drawing a blank on how to do this:
`sudo mkdir -pv /path/to/{folder1,folder2,folder3,folder}`

I know the brackets are a bash function.  

Do I need to do something like `su -s /usr/local/bin/bash -c "mkdir -pv /path/to/{folder1,folder2,folder3,folder}"`


----------



## Jose (Mar 9, 2021)

Bourne Shell Looping
		

Edit: This how you do a for loop in one line

```
for i in `seq 10`; do echo "This is i $i"; done
```


----------



## andrewm659 (Mar 9, 2021)

What if I wanted to run it like I have in my example?  I have done this in the past but for the life of me can't remember.  On linux this would work.


----------



## andrewm659 (Mar 9, 2021)

Figured it out.


----------



## zirias@ (Mar 9, 2021)

When figuring something out, it's often nice to also include the solution: someone else might run into the same problem.

Side note: "On linux this would work" -> No. In Bash, this would work. And while bash is your default shell on almost any Linux system, you can always use a different one. FreeBSD comes with tcsh as your standard shell, I personally don't like it and use zsh instead.

And of course, there's always /bin/sh, which should be POSIX compliant (some Linux dists also use bash for that). But a plain POSIX shell won't support your initial syntax either.


----------



## Jose (Mar 9, 2021)

The example I posted works on both Korn Shell (mksh) and Freebsd's Bourne shell (/bin/sh).

This is something I found on this forum (I forget where) that I consider very useful





						Unix Shells: Bash, Fish, Ksh, Tcsh, Zsh - Hyperpolyglot
					






					hyperpolyglot.org


----------



## SirDice (Mar 9, 2021)

andrewm659 said:


> I know the brackets are a bash function.


I don't see the problem here. It's not a specific bash shell function, it works just fine with a C shell too. As long as we're talking about interactive commands here. Root's shell is set to csh(1), at least by default. For some reason a lot of people assume it's sh(1). 


```
dice@williscorto:~/test % echo $SHELL
/bin/tcsh
dice@williscorto:~/test % mkdir {a,b,c}
dice@williscorto:~/test % ls -l
total 2
drwxr-xr-x  2 dice  dice  2 Mar  9 19:31 a
drwxr-xr-x  2 dice  dice  2 Mar  9 19:31 b
drwxr-xr-x  2 dice  dice  2 Mar  9 19:31 c
dice@williscorto:~/test %
```

It doesn't work with sh(1) though, you just get a literal {a,b,c} named file. So for scripts this is a bad way to create multiple directories with one command. 

```
dice@williscorto:~/test % sh
$ pwd
/home/dice/test
$ mkdir {a,b,c}
$ ls -l
total 1
drwxr-xr-x  2 dice  dice  2 Mar  9 19:33 {a,b,c}
```

For sh(1) scripts I would probably use something like:

```
#!/bin/sh

mydirs="a b c"

for d in $mydirs; do
  mkdir $d
done
```
You can cram this on a one-liner but for the sake of the example I've written this out.


----------



## andrewm659 (Mar 9, 2021)

I ended up doing this:
`sudo /usr/local/bin/bash -c 'mkdir -pv /path/to/{folder1,folder2,folder3,folder4}'`


----------



## Mjölnir (Mar 9, 2021)

The (t)csh(1) has `foreach var ( ... )<ENTER>`, which I learned to like much more than bash(1)'s syntax `for var in ...; do ... done<ENTER>`, because in an interactive session, `foreach` opens the 2nd-ary prompt level & asks you for the commands in the loop.  Then you can iteratively evolve your mini-live-script by preceding every command with `echo`, then close the loop with an `end`.  E.g.
	
	



```
foreach dir ( data{1,2,3} )
foreach? echo $dir
foreach? end
data1
data2
data3
    [ press <UP-ARROW> to recall the previous commands ]
foreach dir ( data{1,2,3} )
foreach? echo mkdir -pv /path/to/$dir
foreach? end
mkdir -pv /path/to/data1
mkdir -pv /path/to/data2
mkdir -pv /path/to/data3
```
etc.pp. when you're satisfied, recall the commands by pressing the <UP-ARROW> and remove the `echo`, which will _fire_ your mini-live-script.


----------



## olli@ (Mar 9, 2021)

Mjölnir said:


> The (t)csh(1) has `foreach var ( ... )<ENTER>`, which I learned to like much more than bash(1)'s syntax `for var in ...; do ... done<ENTER>`,


That’s not bash syntax, it’s standard bourne shell syntax, as specified by POSIX.


> because in an interactive session, `foreach` opens the 2nd-ary prompt level & asks you for the commands in the loop.  Then you can iteratively evolve your mini-live-script by preceding every command with `echo`, then close the loop with an `end`. E.g. […] etc.pp. when you're satisfied, recall the commands by pressing the <UP-ARROW> and remove the `echo`, which will _fire_ your mini-live-script.


That’s one of the reasons why I prefer zsh.  It supports exactly that kind of command line editing, _and_ you can use the standard bourne shell syntax.

(I refrain from linking to the famous “(t)csh considered harmful” article …)


----------



## olli@ (Mar 9, 2021)

andrewm659 said:


> I ended up doing this:
> `sudo /usr/local/bin/bash -c 'mkdir -pv /path/to/{folder1,folder2,folder3,folder4}'`


If those folders really have a common prefix, you can save some typing:
`... mkdir -pv /path/to/folder{1,2,3,4}`
And if the names have actual numbers, you can also do this:
`... mkdir -pv /path/to/folder{1..4}`
(Works with zsh and bash, does _not_ work with (t)csh.)


----------

