-
-
Notifications
You must be signed in to change notification settings - Fork 113
/
Copy pathGet-FileItem.ps1
156 lines (135 loc) · 5.02 KB
/
Get-FileItem.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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
Write-Verbose "Starting $($myinvocation.MyCommand)"
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"
}
} #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 | Select-Object -expandproperty Fullname
}
Write-Verbose "Ending $($myinvocation.MyCommand)"
} #end function