Create directory if it does not exist
Asked Answered
R

13

539

I am writing a PowerShell script to create several directories if they do not exist.

The filesystem looks similar to this

D:\
D:\TopDirec\SubDirec\Project1\Revision1\Reports\
D:\TopDirec\SubDirec\Project2\Revision1\
D:\TopDirec\SubDirec\Project3\Revision1\
  • Each project folder has multiple revisions.
  • Each revision folder needs a Reports folder.
  • Some of the "revisions" folders already contain a Reports folder; however, most do not.

I need to write a script that runs daily to create these folders for each directory.

I am able to write the script to create a folder, but creating several folders is problematic.

Roadside answered 3/6, 2013 at 21:30 Comment(1)
"creating several folders is problematic" - what sort of problem are you having? Are you not sure how to write the cod? Are you getting an error message? Do the folders just not appear after the script is run? Different problems require different solutions.Minelayer
Z
771

Try the -Force parameter:

New-Item -ItemType Directory -Force -Path C:\Path\That\May\Or\May\Not\Exist

You can use Test-Path -PathType Container to check first.

See the New-Item MSDN help article for more details.

Zinovievsk answered 4/6, 2013 at 6:50 Comment(8)
For the lazy, there is a shorthand: md -Force c:\foo\bar\bazEmmetropia
For those who don't want any output when the folder is created, add "| Out-Null" at the endBlip
What will -Force actually do? The documentation says "Forces this cmdlet to create an item that writes over an existing read-only item". Will it delete an existing folder? It should be clear in this answer.Gott
@PeterMortensen In the case of directories, forcing them does not clear out existing contents, it only suppresses the error message saying it's already created. This command will also create any intervening folders necessary, and the contents of those folders are also safe if they already exist.Shuster
Warning: This will proceed silently if there is a file at the path, unlike [System.IO.Directory]::CreateDirectory('path')Jasminjasmina
"will proceed silently if there is a file at the path" - This bug still exists in PowerShell 7.3.1.Yeanling
From docs for New-Item expected behaviour is to overwrite with -ItemType File not -ItemType Directory which instead returns the existing folder object and files. I assume in your testing "will proceed silently if there is a file at the path", you're using -Force with Directory as in this answer. See examples 8 and 9 at learn.microsoft.com/en-us/powershell/module/…Bionics
I had to put quotes around the Path, or it errored out: New-Item : A positional parameter cannot be found that accepts argument. New-Item -ItemType Directory -Force -Path "C:\Path\That\May\Or\May\Not\Exist" or md -Force "C:\Path\That\May\Or\May\Not\Exist".Dehumidifier
I
273
$path = "C:\temp\NewFolder"
If(!(test-path -PathType container $path))
{
      New-Item -ItemType Directory -Path $path
}

Test-Path -PathType container checks to see if the path exists and is a directory. When it does not, it will create a new directory. If the path exists but is a file, New-Item will raise an error (you can overwrite the file by using the -force argument if you are risky).

Immediacy answered 25/8, 2016 at 20:48 Comment(4)
Nice! This silences output if the directory already exists (because it uses test-path).Hognut
Why the option -Force?Joyner
@Joyner to account for Schrödinger's DirectoryBrezhnev
from my test -Force doesn't overwrite file with directory but rather silently fail.Porpoise
M
57
[System.IO.Directory]::CreateDirectory('full path to directory')

This internally checks for directory existence, and creates one, if there is no directory. Just one line and native .NET method working perfectly.

Mikkanen answered 8/8, 2020 at 2:44 Comment(6)
Can I do a local / relative path to my current working directory?Earp
@AaronFranke you can do using [System.IO.Path]::Combine($PWD.Path, 'relativeDirectory')Mikkanen
@AaronFranke yes. As with most of the IO.Directory namespace, just pass the relative path in the parameters. Same is true with their powershell equivalentsPlanchet
@Planchet There can be a problem with "relative" path in powershell because actually things like Set-Location do not affect current directory used by CreateDirectory, as you can see using ::GetCurrentDirectory(). Working directory should be changed using ::SetCurrentDirectory(...) for relativeness to work correctly. (All this for PS 5.1 behaviour)Mikkanen
The suggestion by armannvg on another answer to add | Out-Null to the end if you don't want any output when the folder is created also works for this answer.Parsec
a really rare, great feature of this .NET implementation is that it will create all folders along the path that it will find missing (not only the last / the leaf).Ardelia
P
32

Use:

$path = "C:\temp\"
    
If (!(test-path $path))
{
    md $path
}
  • The first line creates a variable named $path and assigns it the string value of "C:\temp"

  • The second line is an If statement which relies on the Test-Path cmdlet to check if the variable $path does not exist. The not exists is qualified using the ! symbol.

  • Third line: If the path stored in the string above is not found, the code between the curly brackets will be run.

md is the short version of typing out: New-Item -ItemType Directory -Path $path

Note: I have not tested using the -Force parameter with the below to see if there is undesirable behavior if the path already exists.

New-Item -ItemType Directory -Path $path
Pot answered 12/10, 2017 at 16:42 Comment(3)
this also works for a hierarchy of directories md "C:\first\second\third create them all.Wassyngton
in the above, if the third doesnt exists, how can i create a "folder called "third"Eldridge
For a one-liner, how about md $path -Force | Out-Null.Patriarchate
A
20

The following code snippet helps you to create a complete path.

Function GenerateFolder($path) {
    $global:foldPath = $null
    foreach($foldername in $path.split("\")) {
        $global:foldPath += ($foldername+"\")
        if (!(Test-Path $global:foldPath)){
            New-Item -ItemType Directory -Path $global:foldPath
            # Write-Host "$global:foldPath Folder Created Successfully"
        }
    }
}

The above function split the path you passed to the function and will check each folder whether it exists or not. If it does not exist it will create the respective folder until the target/final folder created.

To call the function, use below statement:

GenerateFolder "H:\Desktop\Nithesh\SrcFolder"
Autoerotic answered 7/11, 2017 at 7:21 Comment(2)
This one is not the easiest one, but is a easy one for understanding.Litt
suppose, if iam having a path "\\shared1\folder1\" and i wanna create a LOGS folder in this path, if it doesnt exists, how can i code? because \\shared1\folder1\ , is a variable and not a hardcoded one. i mean, \\shared1\folder1\LOGS must be created if it doesnt exist.Eldridge
B
13

I had the exact same problem. You can use something like this:

$local = Get-Location;
$final_local = "C:\Processing";

if(!$local.Equals("C:\"))
{
    cd "C:\";
    if((Test-Path $final_local) -eq 0)
    {
        mkdir $final_local;
        cd $final_local;
        liga;
    }

    ## If path already exists
    ## DB Connect
    elseif ((Test-Path $final_local) -eq 1)
    {
        cd $final_local;
        echo $final_local;
        liga;  (function created by you TODO something)
    }
}
Baerl answered 15/11, 2013 at 17:32 Comment(0)
S
11

When you specify the -Force flag, PowerShell will not complain if the folder already exists.

One-liner:

Get-ChildItem D:\TopDirec\SubDirec\Project* | `
  %{ Get-ChildItem $_.FullName -Filter Revision* } | `
  %{ New-Item -ItemType Directory -Force -Path (Join-Path $_.FullName "Reports") }

BTW, for scheduling the task please check out this link: Scheduling Background Jobs.

Splendor answered 4/6, 2013 at 9:15 Comment(0)
A
11

There are three ways I know to create a directory using PowerShell:

Method 1: PS C:\> New-Item -ItemType Directory -path "C:\livingston"

Enter image description here

Method 2: PS C:\> [system.io.directory]::CreateDirectory("C:\livingston")

Enter image description here

Method 3: PS C:\> md "C:\livingston"

Enter image description here

Archdeacon answered 26/10, 2016 at 10:58 Comment(1)
Note that ` md ` is simply a Powershell default alias for ` mkdir ` (make directory), a windows command similar to Linux/Unix mkdir. ref: ` Get-Alias md `Midwife
H
4

From your situation it sounds like you need to create a "Revision#" folder once a day with a "Reports" folder in there. If that's the case, you just need to know what the next revision number is. Write a function that gets the next revision number, Get-NextRevisionNumber. Or you could do something like this:

foreach($Project in (Get-ChildItem "D:\TopDirec" -Directory)){
    # Select all the Revision folders from the project folder.
    $Revisions = Get-ChildItem "$($Project.Fullname)\Revision*" -Directory

    # The next revision number is just going to be one more than the highest number.
    # You need to cast the string in the first pipeline to an int so Sort-Object works.
    # If you sort it descending the first number will be the biggest so you select that one.
    # Once you have the highest revision number you just add one to it.
    $NextRevision = ($Revisions.Name | Foreach-Object {[int]$_.Replace('Revision','')} | Sort-Object -Descending | Select-Object -First 1)+1

    # Now in this we kill two birds with one stone.
    # It will create the "Reports" folder but it also creates "Revision#" folder too.
    New-Item -Path "$($Project.Fullname)\Revision$NextRevision\Reports" -Type Directory

    # Move on to the next project folder.
    # This untested example loop requires PowerShell version 3.0.
}

PowerShell 3.0 installation.

Holms answered 3/6, 2013 at 22:12 Comment(0)
R
2

I wanted to be able to easily let users create a default profile for PowerShell to override some settings, and ended up with the following one-liner (multiple statements yes, but can be pasted into PowerShell and executed at once, which was the main goal):

cls; [string]$filePath = $profile; [string]$fileContents = '<our standard settings>'; if(!(Test-Path $filePath)){md -Force ([System.IO.Path]::GetDirectoryName($filePath)) | Out-Null; $fileContents | sc $filePath; Write-Host 'File created!'; } else { Write-Warning 'File already exists!' };

For readability, here's how I would do it in a .ps1 file instead:

cls; # Clear console to better notice the results
[string]$filePath = $profile; # Declared as string, to allow the use of texts without plings and still not fail.
[string]$fileContents = '<our standard settings>'; # Statements can now be written on individual lines, instead of semicolon separated.
if(!(Test-Path $filePath)) {
  New-Item -Force ([System.IO.Path]::GetDirectoryName($filePath)) | Out-Null; # Ignore output of creating directory
  $fileContents | Set-Content $filePath; # Creates a new file with the input
  Write-Host 'File created!';
}
else {
  Write-Warning "File already exists! To remove the file, run the command: Remove-Item $filePath";
};
Rubella answered 29/12, 2016 at 10:21 Comment(0)
S
2

Here's a simple one that worked for me. It checks whether the path exists, and if it doesn't, it will create not only the root path, but all sub-directories also:

$rptpath = "C:\temp\reports\exchange"

if (!(test-path -path $rptpath)) {new-item -path $rptpath -itemtype directory}
Superabundant answered 18/9, 2017 at 12:55 Comment(0)
C
0
$mWarningColor = 'Red'

<#
.SYNOPSIS
    Creates a new directory. 
.DESCRIPTION
    Creates a new directory. If the directory already exists, the directory will
    not be overwritten. Instead a warning message that the directory already
    exists will be output.
.OUTPUT
    If the directory already exists, the directory will not be overwritten.
    Instead a warning message that the directory already exists will be output.
.EXAMPLE    
    Sal-New-Directory -DirectoryPath '.\output'
#>
function Sal-New-Directory {
    param(
        [parameter(mandatory=$true)]
        [String]
        $DirectoryPath
    )
    $ErrorActionPreference = "Stop"
    try {
        if (!(Test-Path -Path $DirectoryPath -PathType Container)) {

            # Sal-New-Directory is not designed to take multiple 
            # directories. However, we use foreach to supress the native output
            # and substitute with a custom message.
            New-Item -Path $DirectoryPath -ItemType Container | `
              foreach {'Created ' + $_.FullName}
        } else {
            Write-Host "$DirectoryPath already exists and" `
                        "so will not be (re)created." `
                        -ForegroundColor $mWarningColor
        }
    } finally {
        $ErrorActionPreference = "Continue"
    }
}

"Sal" is just an arbitrary prefix for my own library. You could remove it or replace it with your own.

Another example (place here because it otherwise ruins stackoverflow syntax highlighting):

Sal-New-Directory -DirectoryPath ($mCARootDir + "private\")
Coextend answered 2/5, 2021 at 12:10 Comment(0)
T
0

Example, create a 'Reports' folder inside of the script's folder.

$ReportsDir = $PSScriptRoot + '\Reports'
$CreateReportsDir = [System.IO.Directory]::CreateDirectory($ReportsDir) 
Trichromatism answered 1/9, 2022 at 2:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.