To add an explanation to your own effective workaround (not including a trailing \
in your argument):
What you're seeing is a bug in Windows PowerShell with respect to how it passes arguments to external programs - this problem has been fixed in PowerShell (Core) 7+.
Behind the scenes, PowerShell (of necessity) translates your single-quoted argument containing spaces to a double-quoted form, because external CLIs can only be assumed to understand "..."
quoting.
The command-line parsing rules used by most CLIs consider the sequence \"
to be an escaped "
character, i.e. a "
character to be considered a verbatim part of the argument rather than delimiting it.
Therefore, a verbatim \
at the end of a double-quoted string must itself be escaped as \\
in order to be recognized as such - this is what Windows PowerShell neglects to do:
That is, Windows PowerShell translates your call as follows:
# Resulting command line as used behind the scenes for actual invocation.
# WinPS: BROKEN, because the \ at the end isn't escaped.
icacls.exe ".\My Digital Editions\"
When icacls.exe
parses this command line, it sees verbatim .\My Digital Editions"
(note the verbatim "
at the end), as reflected in the error message.
PowerShell (Core), by contrast, does perform the necessary escaping:
# Resulting command line as used behind the scenes for actual invocation.
# PowerShell (Core): OK
icacls.exe ".\My Digital Editions\\"
Workarounds:
In a literal path, simply omit a trailing \
- which won't work for a root path, however, and it also assumes that this doesn't change the meaning of the argument from the target program's perspective (it doesn't for icacls.exe
).
Alternatively - which also works for root paths - manually double the trailing \
A robust, cross-edition programmatic solution that doesn't modify the argument is a bit more cumbersome:
icacls.exe $(if ($path.EndsWith('\') -and $PSVersionTable.PSEdition -ne 'Core') { "$path\" } else { $path })
As an aside:
A related bug that affects how "
(double quotes) embedded in arguments are passed to external programs is affects PowerShell (Core) up to 7.2.x - see this answer.