I was making user-entered variable configurable via command line parameters & ran into this weird behaviour:
PS D:> python -c "import sys; print(sys.argv)" -imgs ".\Test V4\Rilsa\" -nl 34
['-c', '-imgs', '.\\Test V4\\Rilsa" -nl 34']
PS D:> python -c "import sys; print(sys.argv)" -imgs ".\TestV4\Rilsa\" -nl 34
['-c', '-imgs', '.\\TestV4\\Rilsa\\', '-nl', '34']
If the name of my folder is Test V4
with a space character, then all following parameters end up in the same argument element '.\\Test V4\\Rilsa" -nl 34'
. There is also a trailing "
quote after the directory name. I tried this again in CMD, thinking it was a Powershell quirk & experienced the same behaviour.
What's going on here? I'm assuming it has something to do with backslashes in Powershell -- though it's the default in Windows for directory paths -- but why do I get diverging behaviour depending on space characters & what's a good way to handle this assuming Windows paths are auto-completed into this form by the shell (i.e. trailing \
)?
You're seeing a bug in Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1), which has since been fixed in PowerShell (Core) 7, as detailed in this answer.
In short, as you've since discovered yourself, the problem occurs when you pass arguments that contain space(s) and end in \
to external programs, because Windows PowerShell - when it constructs the true process command line behind the scenes - blindly encloses such arguments in "..."
, causing most target programs to interpret the closing \"
sequence as an escaped "
char.
(Since arguments without spaces are not subject to this "..."
enclosure, they are not affected.)
Workarounds (required in Windows PowerShell only, but should also work in PowerShell 7):
Manually add a trailing \
to your argument:
# Note the '\\'
python -c "import sys; print(sys.argv)" -imgs ".\Test V4\Rilsa\\" -nl 34
Alternatively, add a trailing space, relying on the fact that on Windows trailing spaces in paths are usually ignored:
# Note the trailing space before the closing "
python -c "import sys; print(sys.argv)" -imgs ".\Test V4\Rilsa " -nl 34
In either case, if the path must be passed via a variable rather than a literal and the variable value may or may not end in \
, use "..."
, i.e. an expandable (interpolating) string, such as "$dirPath\"
or "$dirPath "