create multiple subdirectories

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}"
 
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.
 
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.
 
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).

Code:
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.
Code:
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:
Code:
#!/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.
 
I ended up doing this:
sudo /usr/local/bin/bash -c 'mkdir -pv /path/to/{folder1,folder2,folder3,folder4}'
 
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.
Bash:
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.
 
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 …)
 
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.)
 
Back
Top