I'm trying to get the result code from a running a file search in a powershell function. I'm using .NET for efficiency, and I don't want to compromise that. Now I am trying to obtain some kind of result code from the function (or command) but I don't how to do this.
I can save the command result in a variable, but if there are 10,000+ items, I'm not sure that is a great idea. Here's a POC using EnumerateFiles:
$RES=[IO.Directory]::EnumerateFiles($PWD, "*xxxx.dll", [IO.EnumerationOptions] @{AttributesToSkip='Device,Temporary,SparseFile,ReparsePoint,Compressed,Offline,Encrypted'; RecurseSubdirectories=$true; IgnoreInaccessible=$true})
$RES.Length
# Doesn't output anything! (Why is it not zero?)
$RES=[IO.Directory]::EnumerateFiles($PWD, "*.dll", [IO.EnumerationOptions] @{AttributesToSkip='Device,Temporary,SparseFile,ReparsePoint,Compressed,Offline,Encrypted'; RecurseSubdirectories=$true; IgnoreInaccessible=$true})
$RES.Length
# outputs the length of each path... NOT what I want.
Likewise using $?
always returns True
.
I was also thinking if it would be possible to use output redirection to measure the output somehow. Not sure how this would be done though.
How can I check the result success from a call like this?
(More specifically I would like to check if there are no files found.)
If you want to know if there are any items matching your filter you could use Enumerable.Any
:
function hasany {
[CmdletBinding()]
param([string] $Path = $PWD, [string] $Filter = '*')
$Path = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Path)
$options = [IO.EnumerationOptions]@{
AttributesToSkip = 24384 # Same as Device, Temporary, ...
RecurseSubdirectories = $true
IgnoreInaccessible = $true
}
[System.Linq.Enumerable]::Any(
[System.IO.Directory]::EnumerateFiles($Path, $Filter, $options))
}
hasany -Filter *.dll
Similarly, if you want to know how many, you could use Enumerable.Count
. Both methods are very efficient, specially in .NET 9.
function howmany {
[CmdletBinding()]
param([string] $Path = $PWD, [string] $Filter = '*')
$Path = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Path)
$options = [IO.EnumerationOptions]@{
AttributesToSkip = 24384 # Same as Device, Temporary, ...
RecurseSubdirectories = $true
IgnoreInaccessible = $true
}
[System.Linq.Enumerable]::Count(
[System.IO.Directory]::EnumerateFiles($Path, $Filter, $options))
}
howmany -Filter *.dll
Regarding the question in comments, how could you enable hasany *.dll
and hasany ./dir *.txt
, if you're using $args
instead of named parameters you could do something like this, however there is no validation on how many arguments you're passing, it will only use $args[0]
and $args[1]
in this case.
function hasany {
$options = [IO.EnumerationOptions]@{
AttributesToSkip = 24384 # Same as Device, Temporary, ...
RecurseSubdirectories = $true
IgnoreInaccessible = $true
}
$params = $args.Count -eq 2 ?
(Convert-Path $args[0]), $args[1], $options :
$pwd.Path, $args[0], $options
[System.Linq.Enumerable]::Any(
[System.IO.Directory]::EnumerateFiles.Invoke($params))
}