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