The not equal operator in PowerShell is -ne. It returns True when two values are different, and it ignores case for text:
$state = 'NJ'
if ($state -ne 'NY') { "$state is not New York" }
"'NJ' -ne 'NY': $('NJ' -ne 'NY')"
"'NJ' -ne 'nj': $('NJ' -ne 'nj')"
Output:
NJ is not New York
'NJ' -ne 'NY': True
'NJ' -ne 'nj': False
PowerShell doesn’t support !=. Writing if (5 != 3) fails with “Unexpected token ‘!=’ in expression or statement.” I ran every example in PowerShell 7.6 and Windows PowerShell 5.1, with the same results.
Case-sensitive not equal: -cne
Add a c for a case-sensitive comparison. Use it for passwords, codes and anything where Texas and TEXAS really are different:
"-ne: $('Texas' -ne 'TEXAS')"
"-cne: $('Texas' -cne 'TEXAS')"
Output:
-ne: False
-cne: True
All the other comparison operators are listed in PowerShell comparison operators.
-ne on an array filters it
With a list on the left, -ne returns the items that don’t match instead of True or False. That’s useful for removing a value, but it breaks if statements:
$states = 'NJ', 'NY', 'PA', 'NJ'
"States except NJ: $(($states -ne 'NJ') -join ', ')"
if ($states -ne 'NJ') { 'This runs, even though the list contains NJ' }
if ($states -notcontains 'NJ') { 'NJ is not in the list' } else { 'Use -notcontains to test membership' }
Output:
States except NJ: NY, PA
This runs, even though the list contains NJ
Use -notcontains to test membership

To ask “is this value not in the list”, use -notcontains or -notin. Checking if an array contains a value covers both.
The left side decides the type
When the two sides have different types, PowerShell converts the right side to match the left one. The same numbers can compare differently:
"'10' -ne 10: $('10' -ne 10)"
"10 -ne '10.0': $(10 -ne '10.0')"
"'10.0' -ne 10: $('10.0' -ne 10)"
Output:
'10' -ne 10: False
10 -ne '10.0': False
'10.0' -ne 10: True

In the last line, ‘10.0’ and ’10’ are different strings. Cast values from files or user input with [int] or [decimal] first. PowerShell comparison operators explains this rule for every operator.
Not equal in Where-Object
Use -ne to filter out one value, and -notin to filter out several:
$services = @(
[pscustomobject]@{ Name = 'Spooler'; Status = 'Running' }
[pscustomobject]@{ Name = 'W32Time'; Status = 'Stopped' }
[pscustomobject]@{ Name = 'BITS'; Status = 'Running' }
[pscustomobject]@{ Name = 'WSearch'; Status = 'Paused' }
)
'Not running:'
$services | Where-Object Status -ne 'Running' | ForEach-Object { " $($_.Name) ($($_.Status))" }
'Neither running nor paused:'
$services | Where-Object Status -notin 'Running', 'Paused' | ForEach-Object { " $($_.Name)" }
Output:
Not running:
W32Time (Stopped)
WSearch (Paused)
Neither running nor paused:
W32Time
With real services, run Get-Service | Where-Object Status -ne 'Running'. I used sample objects so the output stays the same.
Not equal to null or empty
On an array, -ne $null removes the null items. Empty strings aren’t null, so they stay unless you check for them too:
$users = 'alice', $null, 'bob', ''
"Without nulls: $(($users -ne $null).Count) items"
"Without nulls or empty strings: $(($users | Where-Object { -not [string]::IsNullOrEmpty($_) }) -join ', ')"
Output:
Without nulls: 3 items
Without nulls or empty strings: alice, bob
For a single value, write $null -ne $value with $null on the left. Checking for null or empty explains why the order matters.
Comparing objects with -ne
Two objects are equal only if they’re the same object. Two separate objects with identical properties still count as not equal:
$a = [pscustomobject]@{ Id = 1001; State = 'TX' }
$b = [pscustomobject]@{ Id = 1001; State = 'TX' }
"`$a -ne `$b: $($a -ne $b)"
"Id values differ: $($a.Id -ne $b.Id)"
"Compare-Object says: $(if (Compare-Object $a $b -Property Id, State) { 'different' } else { 'same' })"
Output:
$a -ne $b: True
Id values differ: False
Compare-Object says: same

Compare the properties you care about, or use Compare-Object, which returns nothing when the listed properties match.
Other “not” comparison operators
-ne has relatives for patterns and lists. Each returns True when the value doesn’t match:
$file = 'q3-report.xlsx'
"-notlike '*.csv': $($file -notlike '*.csv')"
"-notmatch '^q\d': $($file -notmatch '^q\d')"
"-notin 'a','b': $($file -notin 'a.xlsx', 'b.xlsx')"
Output:
-notlike '*.csv': True
-notmatch '^q\d': False
-notin 'a','b': True
Microsoft lists them all in about_Comparison_Operators. Logical operators like -not cover flipping a whole condition.
Frequently Asked Questions
What is the not equal operator in PowerShell?
-ne. For example, $state -ne 'NY' returns True when $state isn’t NY.
Does != work in PowerShell?
No. PowerShell gives “Unexpected token ‘!='”. Use -ne instead, or -not ($a -eq $b).