u/ewild

Why if($path|Test-Path){'do something'} is considered a bad choice?

I came across a recommendation that if($path|Test-Path){'do something'} (which I used to most of the time) is considered a bad choice, while if(Test-Path -path $path){'do something'} is the best practice. Why so?

As I google it, it answers like that:

> The recommendation stands because using the pipeline ($path|Test-Path) introduces massive performance overhead and creates a dangerous blind spot where your script can fail silently if a variable is empty.

> While both statements return a true/false value, passing the path as a direct parameter is safer, cleaner, and significantly faster.

So, should I completely abandon the if($path|Test-Path){'do something'} syntax?

And, moreover, if(([IO.DirectoryInfo]$path).Exists -or ([IO.FileInfo]$path).Exists){'do something'} makes the complete loser of the Test-Path?

Edit 2

To be clear, this is what I was doing yesterday (let's say, at the request of a friend), and what has finally motivated me to search for the question and to ask it here. There could be easily [tens] thousands of Test-Path items (simplified):

$time = [diagnostics.stopwatch]::StartNew()

if(-not $args){
    'no input parameters have been passed; nothing to do here, exiting...'
    sleep -second 3
    exit
}

'input parameters:'|Write-Host -f Yellow
'[0] current source path : {0}' -f $args[0];$sourcePath = $args[0]
'[1] current target path : {0}' -f $args[1];$targetPath = $args[1]

$list = Get-Item -path 'd:\copy_files_from_list.txt'
$filenames = [IO.File]::ReadLines($list)|foreach{$_}
''
'filenames list:'|Write-Host -f Yellow
for ($i=0;$i -lt $filenames.count;$i++){
    '[{0}] : {1}' -f $i,$filenames[$i]|Write-Host -f Green
}
''
'find and copy files from a filenames list into a destination preserving the directory structure'
'phase 1 : files are somewhere within the disk where the $sourcePath resides:'|Write-Host -f Yellow
$path = (Get-Item $sourcePath).PSDrive.Root
$files = Get-ChildItem -path $path -file -force -recurse -EA:silent|Where{$_.Name -in $filenames}
foreach ($file in $files){
    # [IO.Path]::GetRelativePath($path,$file)
    $suffix = [IO.Path]::GetRelativePath($path,$file)
    $destination = [IO.Path]::combine($targetPath,$suffix)
    $destinationPath = ([IO.FileInfo]$destination).Directory
    # Test-Path here is now replaced with [IO.Directory]::Exists()
    if(-not [IO.Directory]::Exists($destinationPath)){
        New-Item $destinationPath -type directory -force|Out-Null
    }
    '{0} >> {1}' -f $file.FullName,$destination
    Copy-Item $file $destination -force
}
'{0} files have been copied' -f $files.count
$firstPhase =  $time.Elapsed
'{0:mm\:ss\.fff} : the first phase timing' -f $firstPhase
''
'...'
''
# finalizing
$time.Stop()
'{0:mm\:ss\.fff} : the total timing by {1}' -f $time.Elapsed,$MyInvocation.MyCommand.Name
sleep -second 33
reddit.com
u/ewild — 5 days ago