Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A better way to check if a path exists or not in PowerShell [closed]

Tags:

powershell

People also ask

How do you check path is exist or not in PowerShell?

Use the Test-Path Cmdlet to Check if Folder Exists in PowerShell. The Test-Path cmdlet determines whether all path elements exist or not in PowerShell. It returns a Boolean value, True if all elements exist, and False if any are missing.

How do you check if a file does not exist in PowerShell?

Use Test-Path to Check if a File Exists in PowerShell It returns $True if the path exists and $False if any element is missing. The -PathType Leaf parameter checks for a file and not a directory. If there is no file named file. txt in the directory New , it returns $False .

How do you check if a file exists and delete it in PowerShell?

Subscribe to ShellGeek!PowerShell Test-Path cmdlet check if file exists or not. If file exists, it will return $True and $False if the file doesn't exist on a specified path. PowerShell Remove-Item cmdlet is used to delete the file if exists from the specified path by the $FileName variable.

Does not exist in PowerShell?

PowerShell Create Directory If Not Exists using Test-Path If a directory exists then it will return $True. If a path or directory is missing or doesn't exist, it will return $False. Using PowerShell New-Item cmdlet, it will create directory if not exists using Test-Path.


If you just want an alternative to the cmdlet syntax, specifically for files, use the File.Exists() .NET method:

if(![System.IO.File]::Exists($path)){
    # file with path $path doesn't exist
}

If, on the other hand, you want a general purpose negated alias for Test-Path, here is how you should do it:

# Gather command meta data from the original Cmdlet (in this case, Test-Path)
$TestPathCmd = Get-Command Test-Path
$TestPathCmdMetaData = New-Object System.Management.Automation.CommandMetadata $TestPathCmd

# Use the static ProxyCommand.GetParamBlock method to copy 
# Test-Path's param block and CmdletBinding attribute
$Binding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($TestPathCmdMetaData)
$Params  = [System.Management.Automation.ProxyCommand]::GetParamBlock($TestPathCmdMetaData)

# Create wrapper for the command that proxies the parameters to Test-Path 
# using @PSBoundParameters, and negates any output with -not
$WrappedCommand = { 
    try { -not (Test-Path @PSBoundParameters) } catch { throw $_ }
}

# define your new function using the details above
$Function:notexists = '{0}param({1}) {2}' -f $Binding,$Params,$WrappedCommand

notexists will now behave exactly like Test-Path, but always return the opposite result:

PS C:\> Test-Path -Path "C:\Windows"
True
PS C:\> notexists -Path "C:\Windows"
False
PS C:\> notexists "C:\Windows" # positional parameter binding exactly like Test-Path
False

As you've already shown yourself, the opposite is quite easy, just alias exists to Test-Path:

PS C:\> New-Alias exists Test-Path
PS C:\> exists -Path "C:\Windows"
True

The alias solution you posted is clever, but I would argue against its use in scripts, for the same reason I don't like using any aliases in scripts; it tends to harm readability.

If this is something you want to add to your profile so you can type out quick commands or use it as a shell, then I could see that making sense.

You might consider piping instead:

if ($path | Test-Path) { ... }
if (-not ($path | Test-Path)) { ... }
if (!($path | Test-Path)) { ... }

Alternatively, for the negative approach, if appropriate for your code, you can make it a positive check then use else for the negative:

if (Test-Path $path) {
    throw "File already exists."
} else {
   # The thing you really wanted to do.
}

Add the following aliases. I think these should be made available in PowerShell by default:

function not-exist { -not (Test-Path $args) }
Set-Alias !exist not-exist -Option "Constant, AllScope"
Set-Alias exist Test-Path -Option "Constant, AllScope"

With that, the conditional statements will change to:

if (exist $path) { ... }

and

if (not-exist $path) { ... }
if (!exist $path) { ... }

Another option is to use IO.FileInfo which gives you so much file info it make life easier just using this type:

PS > mkdir C:\Temp
PS > dir C:\Temp\
PS > [IO.FileInfo] $foo = 'C:\Temp\foo.txt'
PS > $foo.Exists
False
PS > New-TemporaryFile | Move-Item -Destination C:\Temp\foo.txt
PS > $foo.Refresh()
PS > $foo.Exists
True
PS > $foo | Select-Object *


Mode              : -a----
VersionInfo       : File:             C:\Temp\foo.txt
                    InternalName:
                    OriginalFilename:
                    FileVersion:
                    FileDescription:
                    Product:
                    ProductVersion:
                    Debug:            False
                    Patched:          False
                    PreRelease:       False
                    PrivateBuild:     False
                    SpecialBuild:     False
                    Language:

BaseName          : foo
Target            : {}
LinkType          :
Length            : 0
DirectoryName     : C:\Temp
Directory         : C:\Temp
IsReadOnly        : False
FullName          : C:\Temp\foo.txt
Extension         : .txt
Name              : foo.txt
Exists            : True
CreationTime      : 2/27/2019 8:57:33 AM
CreationTimeUtc   : 2/27/2019 1:57:33 PM
LastAccessTime    : 2/27/2019 8:57:33 AM
LastAccessTimeUtc : 2/27/2019 1:57:33 PM
LastWriteTime     : 2/27/2019 8:57:33 AM
LastWriteTimeUtc  : 2/27/2019 1:57:33 PM
Attributes        : Archive

More details on my blog.