String Method TrimEnd not trimming as expected

Hello,

I’m using the String Method TrimEnd to trim a specific portion at the end of a string.

I’m importing the string values from a CSV file and looping it through ForEach-Object. The string value is a path to my NAS.

$osd_path = "D:\OSD\Builder"
Import-Csv "$osd_path\List-SourceNames.csv" | ForEach-Object {
$nas_path_root = $($_.nas_path).TrimEnd("\sources")
}
$nas_path_root

Output:

\\nas\Microsoft\Windows 10 Enterprise LTSC 2021
\\nas\Microsoft\Windows 10 21H2 Pro for Workstation
\\nas\Microsoft\Windows 11 21H2 Pro for Workstation
\\nas\Microsoft\Windows 11 21H2 P
\\nas\Microsoft\Windows Server 2022 LTSC Datacenter GUI
\\nas\Microsoft\Windows Server 2022 LTSC Datacenter C

All but two of them are incorrect. The four that are being trimmed incorrectly above, should look like this:

\\nas\Microsoft\Windows 10 21H2 Pro for Workstations
\\nas\Microsoft\Windows 11 21H2 Pro for Workstations
\\nas\Microsoft\Windows 11 21H2 Pro
\\nas\Microsoft\Windows Server 2022 LTSC Datacenter Core

However, when I tested this same code against a local directory, they all trim correctly:

$osd_path = "D:\OSD\Builder"
Import-Csv "$osd_path\List-SourceNames.csv" | ForEach-Object {
$osd_path_root = "$($_.osd_builds)`\$($_.osd_name)`\$($_.osd_sources)".TrimEnd("\sources")
}
$osd_path_root

The output here shows only /sources was trimmed from the full path; as expected.

D:\OSD\Builder\OSBuilds\Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1566\OS
D:\OSD\Builder\OSBuilds\Windows 10 Pro for Workstations x64 21H2 19044.1526\OS
D:\OSD\Builder\OSBuilds\Windows 11 Pro for Workstations x64 21H2 22000.493\OS
D:\OSD\Builder\OSBuilds\Windows 11 Pro x64 21H2 22000.493\OS
D:\OSD\Builder\OSBuilds\Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000\OS
D:\OSD\Builder\OSBuilds\Windows Server 2022 Datacenter x64 Dev 22509.1000\OS

I even tried using a simple array and looping it with a Foreach statement. Both results are exactly the same as the previous outputs: about_Foreach

$osd_path = "D:\OSD\Builder\OSBuilds\Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1566\OS\sources",
"D:\OSD\Builder\OSBuilds\Windows 10 Pro for Workstations x64 21H2 19044.1526\OS\sources",
"D:\OSD\Builder\OSBuilds\Windows 11 Pro for Workstations x64 21H2 22000.493\OS\sources",
"D:\OSD\Builder\OSBuilds\Windows 11 Pro x64 21H2 22000.493\OS\sources",
"D:\OSD\Builder\OSBuilds\Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000\OS\sources",
"D:\OSD\Builder\OSBuilds\Windows Server 2022 Datacenter x64 Dev 22509.1000\OS\sources"

$nas_path = "\\nas\Microsoft\Windows 10 Enterprise LTSC 2021\sources",
"\\nas\Microsoft\Windows 10 21H2 Pro for Workstations\sources",
"\\nas\Microsoft\Windows 11 21H2 Pro for Workstations\sources",
"\\nas\Microsoft\Windows 11 21H2 Pro\sources",
"\\nas\Microsoft\Windows Server 2022 LTSC Datacenter GUI\sources",
"\\nas\Microsoft\Windows Server 2022 LTSC Datacenter Core\sources"


foreach ($os in $osd_path)
{
    $osd_path_root = $osd_path.TrimEnd("\sources")
}
$osd_path_root

foreach ($os in $nas_path)
{
    $nas_path_root = $nas_path.TrimEnd("\sources")
 }
$nas_path_root

I was using Dr Scripto’s guide on how to Trim Your Strings with PowerShell.

I’m not really sure why the trimming doesn’t work correctly, and I’m perplexed why there would be an obvious difference between the output from a network path and a local file path.

Any insight or help on this would be greatly appreciated.

Thank you…

The code you posted is confusing. So I will use examples to show where your thoughts are flawed.

The method .TrimEnd() works EXACTLY as designed but probably different than you think. :wink:

The .TrimEnd() method removes ANY character independend from its position in the parenthesis from the end of the given string. Here is an example:

"Windows 10\sources".TrimEnd('screuo\')

Instead of the word \sources with the backslash in front of it I scrambled the characters but it still removes all of them from the string. I even omitted one “s”. The result is this:

Windows 10

If you have a string with a character next to the part you want to trim equal to ones you want to trim you end up getting more trimmed away than you want. Here’s an example:

"Windows 10 Pro\sources".TrimEnd('screuo\')

Since the “r” and the “o” of “Pro” is provided as the trim characters they will be removed. The result is this:

Windows 10 P

So if you want to remove the last part of a path I’d recommend using the -replace operator. Here’s an example:

"Windows 10 Pro\sources" -replace '\\sources$'
2 Likes

Hello @Olaf,

Thanks for taking a look at this for me. The TrimEnd is definitely confusing to me when it comes to removing characters from a given string. The leading and trailing blanks is pretty straight forward, but not the method I was trying to achieve.

I ran your examples, and I got the same results. The best part is that I used the -replace option you recommended, and the results worked perfectly for everything.

Input string: \\nas\Microsoft\Windows 11 21H2 Pro\sources

foreach ($os in $nas_path)
{
    $nas_path_root = $nas_path -replace '\\sources'
 }
$nas_path_root

Output string: \\nas\Microsoft\Windows 11 21H2 Pro

I still find it strange that two different strings ending in \sources can have such different results when trying to actually trim \sources. Either way, it’s a battle I hope I never see again.

Thanks again for your help! :+1: :+1:

It’s because you’re using the wrong tool. :wink: .TrimEnd() will remove characters - not words. :point_up_2:t4:

But you should be careful when you change code you don’t fully understand. You omitted the dollar sign. It might not change something in this case but it could change the result in other cases.
Let’s say you have the pattern you want to remove not just at the end of the string.

'\\nas\sources for OS\Microsoft\Windows 11 21H2 Pro\sources' -replace '\\sources'

In this case -replace would remove both occurances from the string. While the pattern I suggested only removes the one at the end:

'\\nas\sources for OS\Microsoft\Windows 11 21H2 Pro\sources' -replace '\\sources$'

Computers are stupid. They will do what you tell them to do. :wink:

I wouldn’t count on that. :wink: :smirk:

1 Like