Note: This solution is only of interest if you need to trim at most 2 trailing \ chars., want to support / path separators too, want to handle root paths correctly or are generally interested in regex techniques.
If it's acceptable to trim any nonempty run of trailing \ chars., i.e., also 3 or more (which is quite likely in this case) and root paths need no special treatment, use Martin Brandl's simple solution.
A solution based on PowerShell's -replace operator with a regular expression that handles both trailing \ and \\ and also works with /, given that PowerShell accepts both \ and / as the path separator (which will also make the solution work with PowerShell Core, the cross-platfom edition):[1]
# Remove at most 2 trailing "\" chars.
PS> 'C:\Ravi\' -replace '[\\/]?[\\/]$'
C:\Ravi
#'# More simply, remove any number of trailing "\" chars.
PS> 'C:\Ravi\' -replace '[\\/]+$' #'# equivalent of 'C:\Ravi\'.TrimEnd('\/')
C:\Ravi
[\\/] is a character class ([...]) that matches a single character that is either \ (escaped as \\ to be treated as a literal) or /.
[\\/]?[\\/] matches one or two \ instances at the end ($) of the string, [\\/]+ more loosely matches one or more (+).
Not specifying a replacement string effectively removes the match from the string; if there is no match, the input string is left as-is.
To demonstrate that the approach works with a variety of paths, including UNC paths:
'C:\Ravi', 'C:\Ravi\', 'C:/Ravi/', 'C:\Ravi\\', '\\foo\bar\', 'C:\', '\' | % {
$_ -replace '[\\/]?[\\/]$'
}
The above yields:
C:\Ravi
C:\Ravi
C:/Ravi
C:\Ravi
\\foo\bar
C:
Note, however, that handling of root paths is problematic: C:\ was transformed to C:, and \ resulted in the empty string.
Fixing that - by leaving a trailing \ in these special cases - requires a significantly more complex regex (slightly simplified by matching any number of trailing path separators):
'C:\Ravi', 'C:\Ravi\', 'C:\', 'C:\\', '\', '\\' | % {
$_ -replace '(?:^((?:[a-z]:)?\\)\\*$)|(.*?)(?:\\+)$', '$1$2'
}
This yields:
C:\Ravi
C:\Ravi
C:\
C:\
\
\
Note how the root paths now end in (one) \.
The special-casing of root paths is cumbersome, which is why it is sometimes preferable to ensure rather than remove a trailing \ or / (e.g., C:\Ravi -> C:\Ravi\), so as to facilitate building paths with simple string concatenation (without having to worry about doubling \ chars.); the regex becomes simple again:
'C:\Ravi', 'C:\Ravi\', 'C:\', 'C:\\', '\', '\\' | % {
($_ -replace '[\\/]+$') + '\'
}
This yields:
C:\Ravi\
C:\Ravi\
C:\
C:\
\
\
Note how all paths now end in (one) \.
[1] Sometimes string manipulation is necessary, but oftentimes you can rely on the Join-Path cmdlet to build paths for you, which handles a trailing \ in the directory part gracefully (e.g., Join-Path C:\Ravi\ file.txt yields C:\Ravi\file.txt); by contrast, a trailing \\ is preserved: Join-Path C:\Ravi\\ file.txt yields C:\Ravi\\file.txt; however, while that isn't pretty, it is generally benign (such paths still work for accessing the filesystem).