To trim a string in PowerShell, call .Trim() to remove spaces from both ends, or .TrimStart() and .TrimEnd() for one side only:
$name = ' Alice Johnson '
"Trim(): [$($name.Trim())]"
"TrimStart(): [$($name.TrimStart())]"
"TrimEnd(): [$($name.TrimEnd())]"
"Tabs and line breaks go too: [$("`tAlice Johnson`r`n".Trim())]"
Output:
Trim(): [Alice Johnson]
TrimStart(): [Alice Johnson ]
TrimEnd(): [ Alice Johnson]
Tabs and line breaks go too: [Alice Johnson]
Below I cover trimming specific characters, the first or last few characters, and text before or after a character. I ran every example in PowerShell 7.6 and Windows PowerShell 5.1, and I point out the one place they differ.
Trim specific characters
Pass the characters you want removed. Trim keeps removing them from the ends until it reaches a different character:
$sku = '---TX-1042---'
$path = 'C:\Reports\2026\'
$code = '000078701'
"Trim('-'): $($sku.Trim('-'))"
"TrimEnd('\'): $($path.TrimEnd('\'))"
"TrimStart('0'): $($code.TrimStart('0'))"
"Trim(' ', '-'): $(' --TX-1042-- '.Trim(' ', '-'))"
Output:
Trim('-'): TX-1042
TrimEnd('\'): C:\Reports\2026
TrimStart('0'): 78701
Trim(' ', '-'): TX-1042

TrimStart(‘0’) is handy for IDs that were padded with zeros, and TrimEnd(‘\’) cleans up folder paths before you join them.
Trim works on characters, not words
TrimEnd(‘.csv’) doesn’t remove the text “.csv”. It removes any of the characters ., c, s and v from the end, which eats letters from the file name:
'orders.csv'.TrimEnd('.csv')
'reports.csv'.TrimEnd('.csv')
'reports.csv' -replace '\.csv$', ''
Output:
order
report
reports
To remove a suffix, anchor it with -replace, as in the last line. Removing characters from a string has more examples.
Remove extra spaces inside a string
Trim only touches the ends. To collapse runs of spaces inside the text, replace \s+ with a single space:
$address = ' 1600 Pennsylvania Ave '
"Trim only: [$($address.Trim())]"
"Trim + collapse: [$(($address -replace '\s+', ' ').Trim())]"
Output:
Trim only: [1600 Pennsylvania Ave]
Trim + collapse: [1600 Pennsylvania Ave]
Hidden characters that Trim() misses
Text pasted from web pages or Excel can carry invisible characters. Trim removes the non-breaking space, but not the zero-width space:
$nbsp = "Austin$([char]0x00A0)"
$zwsp = "Austin$([char]0x200B)"
"Non-breaking space: length $($nbsp.Length), after Trim() $($nbsp.Trim().Length)"
"Zero-width space: length $($zwsp.Length), after Trim() $($zwsp.Trim().Length)"
"After -replace: length $(($zwsp -replace '[\s\u200B\uFEFF]', '').Length)"
Output:
Non-breaking space: length 7, after Trim() 6
Zero-width space: length 7, after Trim() 7
After -replace: length 6
The -replace pattern removes whitespace plus the zero-width space (U+200B) and byte order mark (U+FEFF), the two I run into most.
PowerShell 7 hides the problem in comparisons
In my tests, PowerShell 7’s -eq treated the value with a zero-width space as equal to ‘Austin’, while 5.1 didn’t. .Equals() compares exactly in both:
$zwsp = "Austin$([char]0x200B)"
"-eq 'Austin': $($zwsp -eq 'Austin')"
".Equals('Austin'): $($zwsp.Equals('Austin'))"
Output in PowerShell 7:
-eq 'Austin': True
.Equals('Austin'): False
Output in Windows PowerShell 5.1:
-eq 'Austin': False
.Equals('Austin'): False
So a value can pass an -eq check in 7 and still fail as a hashtable key or in another system. Clean imported text before you use it.
Trim every string in an array
Call .Trim() on the array itself. PowerShell runs it on each item and gives back a new array:
$states = ' Texas', 'Ohio ', ' Utah '
$trimmed = $states.Trim()
$trimmed -join '|'
Output:
Texas|Ohio|Utah
This is also the quickest way to clean a column after splitting a string.
Remove the first or last characters
Remove the first N characters
Substring(4) returns everything from position 4, and Remove(0, 4) deletes the first four. Both drop the INV- prefix here:
$invoice = 'INV-20260928-0042'
$invoice.Substring(4)
$invoice.Remove(0, 4)
Output:
20260928-0042
20260928-0042
Remove the last N characters
Subtract from the length to keep everything except the end. This removes the five-character .xlsx extension:
$file = 'budget-2026.xlsx'
$file.Substring(0, $file.Length - 5)
$file.Remove($file.Length - 5)
Output:
budget-2026
budget-2026
For file names, [IO.Path]::GetFileNameWithoutExtension() is safer because extensions vary in length.
Handle strings shorter than N
Substring throws an error when the string is shorter than the start position. A regex or a Math.Min guard handles short strings:
$id = 'TX'
try { $id.Substring(4) } catch { "Substring(4) failed, 'TX' has only $($id.Length) characters" }
"Regex version: [$($id -replace '^.{0,4}', '')]"
"Safe version: [$($id.Substring([Math]::Min(4, $id.Length)))]"
Output:
Substring(4) failed, 'TX' has only 2 characters
Regex version: []
Safe version: []

Microsoft’s Substring reference lists the exceptions it can throw.
Trim before or after a character
To keep the text before a character, split on it and take the first part. To keep the text after it, find it with IndexOf and take the rest:
$email = 'alice.johnson@contoso.com'
"Before @: $($email.Split('@')[0])"
"After @: $($email.Substring($email.IndexOf('@') + 1))"
Output:
Before @: alice.johnson
After @: contoso.com
IndexOf returns -1 when the character isn’t there, so check before you cut:
$user = 'alice.johnson'
$at = $user.IndexOf('@')
"IndexOf returns $at when the character isn't there"
if ($at -ge 0) { $user.Substring(0, $at) } else { "No @ found, keeping '$user'" }
Output:
IndexOf returns -1 when the character isn't there
No @ found, keeping 'alice.johnson'
Before or after the last occurrence
Use LastIndexOf to split a path into folder and file name. For key=value text, -split with a limit of 2 keeps any later = signs together:
$path = 'C:\Reports\2026\Q3\sales-summary.csv'
"Folder: $($path.Substring(0, $path.LastIndexOf('\')))"
"File: $($path.Substring($path.LastIndexOf('\') + 1))"
"Setting: $(('Server=SQL01;Port=1433' -split '=', 2)[1])"
Output:
Folder: C:\Reports\2026\Q3
File: sales-summary.csv
Setting: SQL01;Port=1433

The about_Split page explains the limit argument.
Trim a string to a maximum length
To cut text down to a fixed length, for a report column or a file name, use Substring with a length check. This version adds an ellipsis:
function Get-Truncated {
param([string]$Text, [int]$Max)
if ($Text.Length -le $Max) { return $Text }
$Text.Substring(0, $Max - 3) + '...'
}
Get-Truncated -Text 'Quarterly sales summary for the Southwest region' -Max 25
Get-Truncated -Text 'Short title' -Max 25
Output:
Quarterly sales summar...
Short title
The .NET String.Trim documentation covers which characters count as white space.
Frequently Asked Questions
How do I trim spaces from a string in PowerShell?
Call $text.Trim(). It removes spaces, tabs and line breaks from both ends. Use TrimStart() or TrimEnd() for one side.
How do I trim a specific character in PowerShell?
Pass it to Trim: '---TX---'.Trim('-') returns TX. You can pass several characters, like .Trim(' ', '-').
Why does TrimEnd(‘.csv’) remove extra letters?
Trim methods treat the argument as a set of characters, not a word. Use -replace '\.csv$', '' to remove the suffix.
How do I remove the first 4 characters of a string?
Use $text.Substring(4). If the string might be shorter, use $text -replace '^.{0,4}', '' instead.
How do I get the text before a character in PowerShell?
Split on it and take the first part: $email.Split('@')[0]. For the text after it, use $email.Substring($email.IndexOf('@') + 1).
Keep working with strings using these guides:
Bijay Kumar is an esteemed author and the mind behind PowerShellFAQs.com, where he shares his extensive knowledge and expertise in PowerShell, with a particular focus on SharePoint projects. Recognized for his contributions to the tech community, Bijay has been honored with the prestigious Microsoft MVP award. With over 15 years of experience in the software industry, he has a rich professional background, having worked with industry giants such as HP and TCS. His insights and guidance have made him a respected figure in the world of software development and administration. Read more.