11

What is the syntax to create multiple directories with PowerShells md (or mkdir, New-Item...) equivalent to the 'nix command mkdir ch{1..9} i.e.

~/parent_dir/  
ch1/  
ch2/  
ch3/  
ch4/  
ch5/  
ch6/  
ch7/  
ch8/  
ch9/  

I've looked in the man pages and get-help for examples, but I do not know the syntax for PowerShell to do such a simple thing. Thank you.

4 Answers 4

17

What is the syntax to create multiple directories with PowerShell

Use the following command:

0..9 | foreach $_{ New-Item -ItemType directory -Name $("ch" + $_) }

How it works:

  • 0..9 the range operator .. generates the sequence of numbers 0, 1, ... 9
  • the numbers are pipelined | to the next command
  • foreach loops (through each number in turn)
  • { ... } is a script block
  • New-Item -ItemType directory -Name $("ch" + $_) creates the directories
  • $_ is an automatic variable that represents the current object in the pipeline (the number)

Example:

> 0..9 | foreach $_{ New-Item -ItemType directory -Name $("ch" + $_) }


    Directory: F:\test


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       25/09/2016     14:57                ch0
d-----       25/09/2016     14:57                ch1
d-----       25/09/2016     14:57                ch2
d-----       25/09/2016     14:57                ch3
d-----       25/09/2016     14:57                ch4
d-----       25/09/2016     14:57                ch5
d-----       25/09/2016     14:57                ch6
d-----       25/09/2016     14:57                ch7
d-----       25/09/2016     14:57                ch8
d-----       25/09/2016     14:57                ch9
14
  • 3
    There is nothing less verbose than entering the following: 1..9 | % $_{ md -name $("ch" + $_) } ?
    – MmmHmm
    Commented Sep 25, 2016 at 14:14
  • 1
    I think so. But I'm no PowerShell expert.
    – DavidPostill
    Commented Sep 25, 2016 at 14:15
  • 1
    It looks OK, but I suggest you try it and see :)
    – DavidPostill
    Commented Sep 25, 2016 at 14:17
  • 1
    a-HA - got it: 1..9 | % $_{ mv ch$_*.* ch$_ } :^D
    – MmmHmm
    Commented Sep 25, 2016 at 14:22
  • 1
    @Mr.Kennedy Couple things. You should try running the git add and see what it returns - keep in mind that $_ inside a foreach is only each individual array entry of the last pipeline item (which means the commit step in your example won't get raw numbers, so adding ch again is probably wrong). Also, in your example, the commits would only(?) run after all adds are done, which means the first commit would get everything... Alternatively, you could use multiple statements (separated by ;) inside a single foreach step.
    – Bob
    Commented Sep 25, 2016 at 15:34
23

You don't need to invoke mkdir multiple times, because New-Item can take an array of paths. For example:

mkdir $(1..9 | %{"ch$_"})

@DavidPostill has explained most of the concepts in his answer. This also takes advantage of string interpolation instead of performing an explicit concatenation. Additionally, the % shorthand is used instead of ForEach-Object, but has the same meaning.

Unfortunately, there does not appear to be an easy way to interpolate a string into an array of strings as in bash.

13
  • 2
    @DavidPostill You've explained in far more detail than I. This might be more of an addendum to your answer :P
    – Bob
    Commented Sep 25, 2016 at 15:20
  • 2
    @DavidPostill please don't delete it - your explanation is very useful
    – MmmHmm
    Commented Sep 25, 2016 at 15:22
  • 3
    Maximally golfed version: md(0..9|%{"ch$_"})
    – Ben N
    Commented Sep 25, 2016 at 15:24
  • 2
    @DavidPostill md is a standard alias for mkdir, which is a PowerShell function. %, as Bob mentioned, is a standard alias for ForEach-Object. Double-quoted strings interpolate variables, so "ch$_" is equivalent to 'ch' + $_. You can look up an alias by running Get-Command (gcm) on it.
    – Ben N
    Commented Sep 25, 2016 at 15:33
  • 1
    @Mr.Kennedy Something like: 1..9 | %{"ch$_"} | %{git add "$_"; git commit -m "$_"} or 1..9 | %{$name = "ch$_"; git add "$name"; git commit -m "$name"}. These comments are getting a bit long now, so if you have further questions - please ask them as questions, or maybe drop into chat.
    – Bob
    Commented Sep 25, 2016 at 15:47
2

Create multiple directories underneath the current directory:

mkdir ('abc','def','jkl') 

The above is a short-hand version of the following. Notice the at-sign included in front of the array of strings and the use of named parameters:

mkdir -Path @('abc','def','jkl')

And if you want to go all the way, the full native command would be:

New-Item -Path @('abc','def','jkl') -ItemType Directory

When using the PowerShell command-line, I use the short version.

When writing a script, especially one for others (who might be new to PowerShell), I tend to write the full native command.

Choose whatever works best for you.

1

I would use for loop version as it is easy to remember and can be applied to many situations. Even it can be used for multiple command.

For an equivalent of this bash command:

for i in {1..9}; do
mkdir ch$i
done

...in PowerShell use:

for($i=1;
$i -le 10;
$i++)
{md ch$i}
4
  • mamum, could you clarify - I get an error when I run your code from the PowerShell command line, or, as a ps1 script: Missing opening '(' after keyword 'for'. This command: foreach ($i in 1..9) {md ch$i} gets me numbered "ch"apter directories, but I don't understand your "for...;do...done" loop.
    – MmmHmm
    Commented Sep 26, 2016 at 17:56
  • The for loop I used here is for bash shell (/bin/sh). I always change my shell to bash as I am used to this shell. For ps, you have to use different syntax for for loop (please see the attached link ss64.com/ps/for.html) Commented Sep 26, 2016 at 18:01
  • 1
    PowerShell: for($i=1; $i -le 10; $i++){md ch$i} thanks mamun, but I'm not yet "Bourne again..." ;) (nor do I know C++, but I think I sorta understand what "$i-le" (if less than or equal to?) and "$i++" (~"i+=1"?) mean and are doing in the command...
    – MmmHmm
    Commented Sep 26, 2016 at 18:16
  • 1
    Yes, the argument ca be read as for (initialize i from 1; as long as i less than or equal to 1; increase i by 1){do stuff iteratively} Commented Sep 26, 2016 at 18:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .