Reputation: 21
Novice scripter here and I have a script that connects to multiple file servers and recurses through directories on them looking for files over 90 days old. All that works great.
I'm using Get-ChildItem -include and -exclude to filter the files I want to report on but I also need to filter out certain directories and get-childitem can't filter directories so I'm piping the results over to a Where-Object that then compares the $_.FullName property to strings I want to exclude.
My problem is that I'm having to adjust the directory names I'm filtering for on a regular basis depending on what clients name their files and managing the script is getting a little out of hand as I have to keep adding -and ($_.FullName -notMatch "BACKUPS") conditions to the get-childitem line.
Here's my relevant code:
$Exclusions = ('*M.vbk','*W.vbk','*Y.vbk')
$Files = Get-ChildItem $TargetFolder -include ('*.vib','*.vbk','*.vbm','*.vrb') -Exclude $Exclusions -Recurse -File |
Where {($_.LastWriteTime -le $LastWrite) -and
($_.FullName -notMatch "BACKUPS") -and
($_.FullName -notMatch "Justin") -and
($_.FullName -notMatch "Monthly") -and
($_.FullName -notMatch "Template") -and
($_.FullName -notMatch "JIMMY") -and
($_.FullName -notMatch "ISAAC")}
I set up the $Exclusions variable to use in Get-ChildItem so that I have a single variable to adjust as needed. Is there a way to condense all the individual Where ($.FullName -notMatch "JIMMY") entries to just use one variable like... Where ($.FullName -notMatch $DirectoryListVariable)?
Basically I just need to make this easier to manage and change if that's possible. If not then I can just keep adding new lines but I'm hoping there is a better way.
Thanks for your time!
Upvotes: 2
Views: 989
Reputation: 437197
Use regex alternation (|
) to match any one of multiple patterns:
# Array of name substrings to exclude.
$namesToExclude = 'BACKUPS', 'Monthly', 'Justin', 'Template', 'JIMMY', 'ISAAC' # , ...
# ...
... | Where-Object {
$_.LastWriteTime -le $LastWrite -and
$_.FullName -notmatch ($namesToExclude -join '|')
}
For case-sensitive matching, use -cnotmatch
As an alternative to defining an array of patterns to then -join
with |
to form a single string ('BACKUPS|Monthly|...'
), you may choose to define your names as part of such a single string to begin with.
Do note that the resulting string must be a valid regex; that is, the individual names are interpreted as regexes (subexpressions) too.
If that is undesired (note that it isn't a problem here, because the specific sample names are also treated literally as regexes), you can escape them with [regex]::Escape()
.
Finally, note that -match
and its variant perform substring (subexpression) matching; to match input strings in full, you need to anchor the expressions, namely with ^
(start of the string) and $
(end of the string); e.g.
'food' -match 'oo'
is $true
, but 'food' -match '^oo$'
is not ('oo' -match '^oo$'
is).
Upvotes: 4