PowerShell är full av data. Get-Process visar hundratals processer. Get-Service listar alla tjänster. Get-ChildItem returnerar tusentals filer. Men du behöver oftast bara ett fåtal av dem.
Här kommer Where-Object in. Det filtrerar resultat så du bara ser vad du behöver. Men många administratörer använder det långsamt eller på ett sätt som inte skalar upp. Låt oss lära oss rätt.
Where-Object är ett PowerShell-kommando som filtrerar objekt baserat på ett villkor. Det tar varje objekt från en pipeline och säger "håll detta objekt om det uppfyller mitt villkor — annars kassera det".
Det är grunden för nästan allt avancerad PowerShell-arbete. Om du inte kan Where-Object kan du inte PowerShell riktigt.
Get-Process | Where-Object {$_.Name -eq "powershell"}Detta visar bara PowerShell-processen, inte alla processer. Låt oss bryta ner syntaxen:
$_ = det aktuella objektet i pipelinen (processen)
.Name = objektets Name-egenskap
-eq = "är lika med"
"powershell" = värdet vi jämför med
# Processer som använder mer än 100 MB minne
Get-Process | Where-Object {$_.Memory -gt 100MB}
# Tjänster som INTE är igång
Get-Service | Where-Object {$_.Status -ne "Running"}
# Filer som är större än 1 GB
Get-ChildItem -Recurse | Where-Object {$_.Length -gt 1GB}
# Användare vars namn börjar med "admin"
Get-LocalUser | Where-Object {$_.Name -like "admin*"}De viktigaste jämförelserna:
-eq = är lika med | -ne = inte lika med | -gt = större än | -lt = mindre än | -ge = större än eller lika med | -le = mindre än eller lika med | -like = liknar (med wildcard)
# Processer som börjar med "s" OCH använder mer än 50 MB
Get-Process | Where-Object {
($_.Name -like "s*") -and ($_.Memory -gt 50MB)
}
# Tjänster som INTE är igång och INTE är disabled
Get-Service | Where-Object {
($_.Status -ne "Running") -and ($_.StartType -ne "Disabled")
}
# Filer från denna mappen som är större än 1 MB ELLER större än 1 år gamla
Get-ChildItem | Where-Object {
($_.Length -gt 1MB) -or (((Get-Date) - $_.LastWriteTime).Days -gt 365)
}-and = båda villkoren måste vara sant | -or = minst ett villkor måste vara sant | -not eller ! = invertera villkoret
Många skriver Where-Object på ett långt sätt. Men PowerShell har genvägar:
Get-Process | Where-Object {$_.Name -eq "powershell"}Get-Process | Where {$_.Name -eq "powershell"}Get-Process -Name "powershell"
Den sista metoden är ofta snabbast — många cmdlets har redan inbyggd filtrering!
Misstag 1: Hämta allt och filtrera sedan
Get-ChildItem C:\ -Recurse | Where-Object {$_.Name -like "*.log"}Get-ChildItem C:\ -Recurse -Filter "*.log"
Om möjligt — filtrera redan när du hämtar data, inte efter.
Misstag 2: Jämföra siffror som text
Get-ChildItem | Where-Object {$_.Length -gt "1000000"}
# Detta jämför som text, inte siffror!Get-ChildItem | Where-Object {$_.Length -gt 1MB}PowerShell förstår enheter som MB, GB, KB. Använd dem!
Misstag 3: Forgetting case sensitivity
Get-Process | Where-Object {$_.Name -eq "PowerShell"}
# Fungerar inte — processnamnet är "powershell" (litet)Get-Process | Where-Object {$_.Name -like "powershell"}
# -like är case-insensitive per default-eq är case-sensitive. -like och -match är case-insensitive. Var försiktig!
1. Filtrera så tidigt som möjligt:
Get-ChildItem C:\ -Recurse | Where-Object {$_.Length -gt 100MB}
# Hämtar tusentals filer först, filtrerar sedanGet-ChildItem C:\ -Recurse -ErrorAction SilentlyContinue |
Where-Object {$_.Length -gt 100MB}2. Använd Where-Object -Property när möjligt:
Get-Process | Where-Object {$_.Memory -gt 100MB}Get-Process | Where-Object -Property Memory -GT 100MB
Den andra syntaxen är ofta snabbare på stora datamängder.
3. Kombinera villkor effektivt:
Get-Process |
Where-Object {$_.Memory -gt 50MB} |
Where-Object {$_.Name -like "s*"}Get-Process | Where-Object {
($_.Memory -gt 50MB) -and ($_.Name -like "s*")
}En Where-Object med kombinerade villkor är snabbare än flera!
# Hitta alla loggfiler större än 1 GB i system32
Get-ChildItem C:\Windows\System32\winevt\Logs -Filter "*.evtx" |
Where-Object {$_.Length -gt 1GB}
# Ännu bättre — lägg till skapningsdatum
Get-ChildItem C:\Windows\System32\winevt\Logs -Filter "*.evtx" |
Where-Object {
($_.Length -gt 1GB) -and ((Get-Date) - $_.CreationTime).Days -lt 30
} |
Select-Object Name, Length, CreationTime
# Om du behöver radera dem (var försiktig!)
Get-ChildItem C:\Windows\System32\winevt\Logs -Filter "*.evtx" |
Where-Object {$_.Length -gt 1GB -and (Get-Date) - $_.CreationTime).Days -lt 7} |
Remove-Item -Force✓ Fördelar
- Extremt flexibelt
- Kan kombinera många villkor
- Lätt att läsa (när det är rätt)
- Fungerar på alla objekt-typer
- Kan byggas dynamiskt
- Snabbt när det används rätt
- Kan även modifiera objekt
✗ Nackdelar
- Långsamt på enorma datamängder
- Case-sensitivity kan orsaka problem
- Lätt att skriva fel syntax
- Script blocks kan bli komplexa
- Ibland redan inbyggd filtrering finns
- Kan slöa ned pipeline
- Svårt att debugga komplexa filter
// SNABB REFERENS: WHERE-OBJECT JÄMFÖRELSER
- -eq | Är lika med (case-sensitive)
- -ne | Inte lika med
- -gt | Större än
- -lt | Mindre än
- -ge | Större än eller lika
- -le | Mindre än eller lika
- -like | Liknar (med wildcard, case-insensitive)
- -match | Regex-match (case-insensitive)
- -and | Båda villkor måste vara sant
- -or | Minst ett villkor måste vara sant
// CHECKLIST: INNAN DU SKRIVER WHERE-OBJECT
- Har cmdlet:en redan inbyggd filtrering? (-Name, -Filter, osv)
- Kan jag filtrera vid källan istället för efter?
- Är jag medveten om case-sensitivity?
- Jämför jag rätt typ av data? (siffror vs text)
- Kan jag kombinera villkor i EN Where-Object istället för flera?
- Behöver jag -Property syntax eller script block?
- Kommer detta att köras på stora datamängder? (optimera då)