I'm trying to filter a list of changed files in git using Powershell 7. I want only the file paths that begin with 'packages' or 'database'. When I run the code, the results are not filtered and everything is returned. How would I get the filtering to work? I'm new to Powershell scripting.
Here is my code:
$editedFiles = git diff HEAD [git commit id] --name-only
$editedFiles | ForEach-Object {
$sepIndex = $_.IndexOf('/')
if($sepIndex -gt 0 -and ($_ -contains 'packages' -or 'database')) {
Write-Output $_
}
}
Couple of things to watch out for here:
-contains
is a collection containment operator - for strings, you'll want either the -like
wildcard comparison operator:
$_ -like "*packages*"
or the -match
regex operator:
$_ -match 'package'
The other thing to watch out for here is the -or
operator - it only takes boolean operands ($true
/$false
), and if you pass it anything else, it'll convert the operands to [bool]
if necessary.
That means that the following kind of statement:
$(<# any expression, really #>) -or 'non-empty string'
ALWAYS returns $true
- because a non-empty string evaluates to $true
when converted to [bool]
.
Instead, you'll want to change two separate comparisons:
$_ -like '*packages*' -or $_ -like '*database*'
Alternatively, you can use the -match
operator once, by using an alternation (|
):
$_ -match 'package|database'
And end up with something like:
$editedFiles | ForEach-Object {
$sepIndex = $_.IndexOf('/')
if($sepIndex -gt 0 -and $_ -match 'package|database') {
Write-Output $_
}
}
If filtering is all you intend to do in the ForEach-Object
block, you might as well use Where-Object
- it's designed exactly for that :)
$editedFiles | Where-Object {
$_.IndexOf('/') -gt 0 -and $_ -match 'package|database'
}