How to Check if a String Starts With Text in PowerShell

The quickest PowerShell string starts with test is the StartsWith() method, which returns True or False:

'Austin, TX'.StartsWith('Aus')   # True

StartsWith() is case-sensitive, so I’ll also show the case-insensitive options, the -like and -match operators, and two traps where PowerShell 7 and Windows PowerShell 5.1 give different answers.

Check if a string starts with text using StartsWith()

The method compares the beginning of the string with the value you pass. Add a StringComparison value to ignore case:

$city = 'Austin, TX'
$city.StartsWith('Aus')
$city.StartsWith('aus')
$city.StartsWith('aus', [StringComparison]::OrdinalIgnoreCase)
$city.StartsWith('aus', 'OrdinalIgnoreCase')

Output:

True
False
True
True
PowerShell 7 StartsWith returns False for a different case until OrdinalIgnoreCase is passed
StartsWith() is case-sensitive unless you pass OrdinalIgnoreCase (PowerShell 7)

Lowercase ‘aus’ returned False until I passed OrdinalIgnoreCase. PowerShell converts the plain string ‘OrdinalIgnoreCase’ to the enum, so the shorter last line works too.

Without a StringComparison, StartsWith(string) uses the current culture. Ordinal is the safer pick for IDs, file names, and codes; see other ways to compare strings in PowerShell for full matches.

StartsWith() differences in PowerShell 7 vs Windows PowerShell 5.1

PowerShell 7 runs on modern .NET, which adds a StartsWith(char) overload. Windows PowerShell 5.1 runs on .NET Framework, which doesn’t have it:

$order = 'INV-2026-0142'
'Overloads:     ' + $order.StartsWith.OverloadDefinitions.Count
'Char overload: ' + $order.StartsWith([char]'I')
'Null value:    ' + $order.StartsWith($null)

Output:

Overloads:     4
Char overload: True
Null value:    False
Windows PowerShell 5.1 StartsWith null returns True and has three overloads
In 5.1, StartsWith($null) returns True because $null becomes an empty string (Windows PowerShell 5.1)

This screenshot is Windows PowerShell 5.1: three overloads, and StartsWith($null) returned True. PowerShell turned $null into an empty string, and every string starts with an empty string.

PowerShell 7 listed four overloads and returned False for the same call, because it picked the char overload. The [char] call worked in both, since 5.1 quietly converts the char to a string.

So never pass a variable that might be empty without checking it first. IsNullOrEmpty catches empty prefixes before they turn every check into True on 5.1.

Use -like ‘text*’ for a case-insensitive starts with check

The -like operator matches a wildcard pattern, and a trailing * means “anything after this”. It ignores case by default, while -clike respects it:

$name = 'Maria Lopez'
$name -like 'mar*'
$name -clike 'mar*'
$name -notlike 'Tom*'

$title = '[Draft] Budget 2026'
$title -like '[Draft]*'
$title -like ([WildcardPattern]::Escape('[Draft]') + '*')

Output:

True
False
True
False
True

The first three lines are True, False, True. The fourth one surprised me: square brackets are wildcard characters too, so ‘[Draft]*’ means “one of D, r, a, f, t” and returns False.

[WildcardPattern]::Escape() makes the brackets literal. The full guide to the -like operator covers ? and the other wildcards.

Use -match ‘^text’ with a regular expression

With -match, the ^ anchor ties the pattern to the start of the string. Escape the prefix if it contains regex characters like + . ( or $:

$product = 'C++ Starter Kit'
$product -match ('^' + [regex]::Escape('C++'))
$product -cmatch '^c'
try { $product -match '^C++' }
catch { "Failed. $($_.Exception.Message)" }

Output:

True
False
Failed. Invalid pattern '^C++' at offset 4. Nested quantifier '+'.

The output above is from PowerShell 7. Windows PowerShell 5.1 returned the same True and False, but its error reads parsing "^C++" - Nested quantifier +. instead.

-cmatch makes the regex case-sensitive. The -match operator and $Matches work the same for any pattern, and the number case has its own guide on how to check if a string starts with a number.

How do I check if a string starts with one of several values?

Put the prefixes in an array and test each one, or join them into one regex with alternation:

$prefixes = 'INV-', 'PO-', 'CR-'
$docs = 'INV-1001', 'po-2044', 'QT-3100', 'CR-0007'

foreach ($doc in $docs) {
    $hit = $prefixes | Where-Object { $doc.StartsWith($_, 'OrdinalIgnoreCase') }
    '{0,-9} {1}' -f $doc, [bool]$hit
}
'Regex: ' + (($docs -match '^(INV|PO|CR)-') -join ', ')

Output:

INV-1001  True
po-2044   True
QT-3100   False
CR-0007   True
Regex: INV-1001, po-2044, CR-0007

Both approaches matched po-2044 regardless of case and skipped the quote QT-3100. Don’t reach for -contains here; the -contains operator checks whole items in a collection, not prefixes.

Filter arrays and files that start with a prefix

Inside Where-Object, any of the three checks works on a property. Here I filter customers by city and invoice files by name:

$customers = @(
    [pscustomobject]@{ Name = 'Dana Reyes';  City = 'Denver' }
    [pscustomobject]@{ Name = 'Tom Baker';   City = 'Dallas' }
    [pscustomobject]@{ Name = 'Maria Lopez'; City = 'Miami' }
)
$customers | Where-Object { $_.City -like 'D*' } | ForEach-Object Name

Get-ChildItem -Path .\Prefix -File |
    Where-Object { $_.Name.StartsWith('INV-') } |
    ForEach-Object Name
'Filter: ' + ((Get-ChildItem -Path .\Prefix -Filter 'inv*').Name -join ', ')

Output:

Dana Reyes
Tom Baker
INV-1001.pdf
INV-1002.pdf
Filter: INV-1001.pdf, INV-1002.pdf, inventory.xlsx