PowerShell Test-Path: Check If a File or Folder Exists

Test-Path is the PowerShell cmdlet that checks whether a file, folder or other path exists. It returns True or False, so it drops straight into an if statement:

$file = 'C:\psfaqs\Reports\q3-sales.xlsx'

if (Test-Path -Path $file) {
    "Found $file"
}
else {
    "Missing $file"
}

Test-Path -Path 'C:\psfaqs\Reports\q4-sales.xlsx'

Output:

Found C:\psfaqs\Reports\q3-sales.xlsx
False

It never throws an error for a missing path, which makes it the safest check before you read, copy or delete something.

I ran each example in PowerShell 7.6 and Windows PowerShell 5.1. They mostly agree, but blank paths and a couple of parameters behave differently, and I show both results there.

Check if a file or a folder exists

By default, Test-Path returns True for a file or a folder. Add -PathType when it matters which one: Leaf means a file and Container means a folder:

Test-Path -Path C:\psfaqs\Reports -PathType Container
Test-Path -Path C:\psfaqs\Reports -PathType Leaf
Test-Path -Path C:\psfaqs\Reports\q3-sales.xlsx -PathType Leaf

Output:

True
False
True
PowerShell Test-Path -PathType Leaf and Container to check a file or folder
Checking for a file or a folder (PowerShell 7)

Use -PathType Leaf before reading a file. Otherwise a folder with the same name would pass the check and the read would fail.

A common next step is creating the folder when it’s missing, as shown in creating a folder if it doesn’t exist.

How do I create a folder if it doesn’t exist?

Combine -not and Test-Path. I ran the check twice to show both branches:

$folder = 'C:\psfaqs\Archive'

foreach ($run in 1, 2) {
    if (-not (Test-Path -Path $folder -PathType Container)) {
        New-Item -Path $folder -ItemType Directory | Out-Null
        "Run $($run): created $folder"
    }
    else {
        "Run $($run): $folder already exists"
    }
}

Output:

Run 1: created C:\psfaqs\Archive
Run 2: C:\psfaqs\Archive already exists

If you only need the folder to exist, New-Item -ItemType Directory -Force does it in one step and doesn’t fail when the folder is already there. See how to create a folder if it doesn’t exist.

Check for files with a wildcard

Test-Path accepts wildcards, so you can check whether any file of a type is in a folder:

Test-Path -Path C:\psfaqs\Reports\*.xlsx
Test-Path -Path C:\psfaqs\Reports\*.pdf

Output:

True
False

File names with square brackets

The flip side is that [ and ] are wildcard characters too. A file named budget[final].xlsx isn’t found with -Path:

Test-Path -Path 'C:\psfaqs\Reports\budget[final].xlsx'
Test-Path -LiteralPath 'C:\psfaqs\Reports\budget[final].xlsx'

Output:

False
True
PowerShell Test-Path returns False for a file name with brackets unless you use -LiteralPath
-Path vs -LiteralPath (Windows PowerShell 5.1)

-LiteralPath treats every character as part of the name. Use it whenever the path comes from user input or a file listing.

Hidden files

Unlike Get-ChildItem, Test-Path finds hidden files without -Force:

Test-Path -Path C:\psfaqs\Reports\desktop.ini
(Get-Item -Path C:\psfaqs\Reports\desktop.ini -Force).Attributes

Output:

True
Hidden

Test-Path with an empty or blank path

This is where the two versions differ most. In PowerShell 7, an empty or blank path simply returns False:

Test-Path -Path ''
Test-Path -Path '   '

Output in PowerShell 7:

False
False

Windows PowerShell 5.1 throws an error for the empty string. Worse, it returns True for a path made of spaces:

Test-Path : Cannot bind argument to parameter 'Path' because it is an empty string.
At C:\psfaqs\blank.ps1:1 char:17
+ Test-Path -Path ''
+                 ~~
    + CategoryInfo          : InvalidData: (:) [Test-Path], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.Test
   PathCommand

True

A variable that’s empty because a lookup failed can make a 5.1 script think a path exists. Check for a blank value first, and the result is the same in both versions:

foreach ($path in '', '   ', 'C:\psfaqs\Reports') {
    $exists = -not [string]::IsNullOrWhiteSpace($path) -and (Test-Path -Path $path)
    "[$path] exists: $exists"
}

Output:

[] exists: False
[   ] exists: False
[C:\psfaqs\Reports] exists: True

Check that a path is valid without creating it

-IsValid checks only the syntax. It’s handy for validating a path a user typed before you create anything:

Test-Path -Path 'C:\psfaqs\New Reports\summary.txt' -IsValid
Test-Path -Path 'C:\psfaqs\New Reports\summary.txt'
Test-Path -Path 'C:\psfaqs\Reports\Q3|summary.txt' -IsValid

Output:

True
False
False

The first path is valid even though it doesn’t exist yet. The third contains |, which Windows doesn’t allow in file names.

Check if a file is older than a date

On file system paths, -OlderThan and -NewerThan compare the last write time. The budget file was last changed 90 days ago:

$cutoff = (Get-Date).AddDays(-30)

Test-Path -Path C:\psfaqs\Reports\budget.xlsx -OlderThan $cutoff
Test-Path -Path C:\psfaqs\Reports\q3-sales.xlsx -OlderThan $cutoff

Output:

True
False

In Windows PowerShell 5.1, these parameters can’t be combined with -PathType, and you get “A parameter cannot be found that matches parameter name ‘OlderThan'”. PowerShell 7.5 fixed that, so this works in 7.6:

Test-Path -Path C:\psfaqs\Reports\budget.xlsx -PathType Leaf -OlderThan (Get-Date).AddDays(-30)

Output in PowerShell 7:

True

Test registry keys and environment variables