functions/Get-FileItem.ps1
|
function Get-FileItem { [cmdletbinding(DefaultParameterSetName = 'Default')] [OutputType('System.IO.FileInfo', 'System.Boolean')] [alias('pswhere')] param( [Parameter( Position = 0, Mandatory, HelpMessage = 'Enter a filename or pattern to search for')] [ValidateNotNullOrEmpty()] [string[]]$Pattern, [switch]$Regex, [Parameter(ParameterSetName = 'Path')] [string[]]$Path, [Parameter(ParameterSetName = 'Path')] [switch]$Recurse, [switch]$Full, [switch]$Quiet, [switch]$First ) #region private helper function <# The Resolve-EnvVariable function is used by Get-FileItem to resolve any paths that might contain environmental names like %WINDIR% or %USERNAME% #> function Resolve-EnvVariable { [cmdletbinding()] param( [Parameter(Position = 0, Mandatory = $True, HelpMessage = 'Enter a string that contains an environmental variable like %WINDIR%')] [ValidatePattern('%\S+%')] [string]$String ) Write-Verbose "Starting $($MyInvocation.MyCommand)" Write-Verbose "Resolving environmental variables in $String" [environment]::ExpandEnvironmentVariables($string) Write-Verbose "Ending $($MyInvocation.MyCommand)" } #end Resolve-EnvVariable function #endregion #This is the main part of Get-FileItem #tags are used for categorizing the command #cmdTags = file Write-Verbose "Starting $($MyInvocation.MyCommand)" Write-Verbose "Running under PowerShell version $($PSVersionTable.PSVersion)" Write-Verbose "Searching for $pattern" Write-Verbose "Quiet mode is $Quiet" Write-Verbose "Full mode is $Full" if ($path) { #use specified path or array of paths $paths = $path } else { #use %PATH% system environmental variable #split %PATH% and weed out any potential duplicates or null values $splitChar = [System.IO.Path]::PathSeparator $paths = $env:PATH.Split($splitChar) | Select-Object -Unique | Where-Object { $_ } } #define a variable to hold results $results = @() #foreach path search for the pattern foreach ($path in $paths) { #if path has an environmental variable, resolve it first if ($path.Contains('%')) { Write-Verbose 'Resolving environmental variables found in the path' $path = Resolve-EnvVariable -string $path } #Validate path is still good Write-Verbose "Testing $path" if (Test-Path -Path $path) { Write-Verbose "Searching $path" #search for each pattern foreach ($p in $pattern) { #define parameters to splat to Get-ChildItem #save errors to a variable to display later #suppressing error messages for now which are typically for access denied to system folders $dirParams = @{ Path = $path Recurse = $Recurse Force = $True ErrorAction = 'SilentlyContinue' ErrorVariable = 'ev' } if (-not $regex) { $dirParams.add('Filter', $p) } Write-Verbose "...for $p" #not thrilled with this structure but it works if ($Regex) { Write-Verbose '...as regex' $results += (Get-ChildItem @dirParams).where( { $_.name -match $p }) } elseif ($Regex -and $first) { Write-Verbose '...as regex' $results += (Get-ChildItem @dirParams).where( { $_.name -match $p }) | Select-Object -First 1 } elseif ($First) { $results += Get-ChildItem @dirParams | Select-Object -First 1 } else { $results += Get-ChildItem @dirParams } } #foreach p Write-Verbose 'Evaluating results' #process errors foreach ($item in $ev) { if ($item.exception.getType().name -eq 'UnauthorizedAccessException') { Write-Warning $item.exception.message } else { Write-Error "$($item.exception.message) [$($item.Exception.getType().name)]" } } } #if test path else { Write-Warning "Failed to verify path location $Path" } } #foreach $count = ($results | Measure-Object).count Write-Verbose "Found $count matches" if (($count -gt 0) -and $Quiet) { #if Quiet and results found write $True $True } elseif (($count -eq 0) -and $Quiet) { $False } elseif (($count -gt 0) -and $Full) { #if results found and write file results $results } else { #else just write full name ($results).FullName } Write-Verbose "Ending $($MyInvocation.MyCommand)" } #end function #EOF |