Question

powershell equivalent of linux "mkdir -p"?

How can I get the powershell "mkdir" command to act exactly like Linux's mkdir -p command?

Under Linux, mkdir -p will create nested directories, but only if they don't exist already. For example, suppose you have a directory /foo that you have write permissions for. mkdir -p /foo/bar/baz creates bar and baz within bar under existing /foo. You run the same command over again, you will not get an error, but nothing will be created.

 46  26794  46
1 Jan 1970

Solution

 40

You can ignore errors in PowerShell with the -ErrorAction SilentlyContinue parameter (you can shorten this to -ea 0). The full PowerShell command is

New-Item /foo/bar/baz -ItemType Directory -ea 0

You can shorten this to

md /foo/bar/baz -ea 0

(You can also type mkdir instead of md if you prefer.)

Note that PowerShell will output the DirectoryInfo object it creates when using New-Item -ItemType Directory (or the md or mkdir aliases). If you don't want any output, you can pipe to Out-Null.

EDIT: Of course, this is not a feature-for-feature "behaves exactly and precisely the same as mkdir -p" command. The point here is to provide information about how to implement similar functionality, with the understanding that different tools likely have different behavioral characteristics.

2017-11-17

Solution

 17

The PowerShell equivalent of Unix
mkdir -p ...
is
$null = New-Item -Type Directory -Force ...

-Force, like -p, implements desired-state logic, which ensures two things:

  • It creates intermediate directories in the target directory path that may not exist yet on demand (New-Item -Type Directory, unlike Unix mkdir, even does that by default).[1]

  • It succeeds if the target directory already exists.

One crucial difference: Unless an error occurs:

  • mkdir -p produces no output.
  • By contrast, New-Item -Type Directory outputs a [System.IO.DirectoryInfo] instance representing the target directory. Thus, to emulate the behavior of mkdir -p, this output must be discarded, which is best done by assigning to $null ($null = New-Item ...)

Caveat:

  • On Windows, mkdir is a built-in wrapper function that passes arguments through to New-Item -Type Directory[2]

  • On Unix-like platforms - in the cross-platform PowerShell [Core] v6+ edition - mkdir is not a built-in command, and instead defers to the platform-native external mkdir utility.

  • Thus, if your scripts need to be cross-platform, use New-Item explicitly.


Note: If you omit -Force and simply silence errors, as shown in Bill Stewart's answer (with -ErrorAction SilentlyContinue, which, however, still records the error (in the automatic $Error variable), or with -ErrorAction Ignore, which ignores it altogether), you get similar behavior, except that:

  • The output behavior will vary situationally:

    • If the target directory already exists, no output is produced (because an error occurs that is ignored), whereas if the target directory is created, a [System.IO.DirectoryInfo] instance representing it is returned.
  • If the target directory already exists, the automatic $? variable will signal $false, even though from the perspective of the desired target state, the prior existence of the target directory should be considered a success case (mkdir -p indeed indicates success in that case, and so does New-Item -ItemType Directory with -Force).

  • Unexpected errors will be hidden too, such as the inability to create the directory due to lack of permissions.

    • In other words: Without taking additional actions, you won't know if the command failed (you'd have to test its existence explicitly, given that $? won't tell you whether a true error occurred).
  • A fundamental difference between New-Item -Type Directory and Unix mkdir is that only the former creates intermediate directories on demand by default.[1]
    mkdir only does so with -p.


[1] However, you do need -Force if you're creating a file whose parent directory doesn't exist yet. Creating a file requires either not passing a -Type (aka -ItemType) argument or using -Type File.

[2] More specifically, it is a proxy (wrapper) function that provides a -Type Directory argument by default. Loosely speaking: it's an alias for New-Item that defaults to creating directories, via a "baked in" -Type Directory argument.

2020-12-05