You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Broken tab-completion with file or directory names with spaces in the context of tilde-prefixed paths (~) #20851
That is, the unquoted status of the initial ~ should be preserved.
Actual behavior
'~/a test''~/a test''~/a test'
That is, all expansions resulted in inappropriate quoting in that the previously unquoted~ - required to trigger PowerShell's tilde-expansion emulation when calling external programs - is now quoted.
Quoted part of path also does not work in pwsh with native utilities:
237dmitry, yes that's the related bug linked to in the initial post (#20754).
What does $f returns to cat, quoted Fullpath or space-escaped Fullpath?
Neither, because - unlike on Windows - there is no such a thing as a process command line on Unix-like platforms, only an array of verbatim arguments (in the case at hand, it is the value of $f.ToString())
I understand that some (or all) Unix shells have this behavior so I can understand why people would want it to be consistent across the different shells. However, in my eyes the desired behavior seems a bit weird. To me a string is a string, it doesn't matter if you use single quotes, double quotes or no quotes at all, as long as you use whatever escape rules apply to the string type during assignment you are golden.
I can't think of any other example in PowerShell where a string is treated differently, depending on how it was quoted. Can you?
MartinGC94, yes, the distinction should not and does not matter in PowerShell, but PowerShell's emulation of both the tilde expansion and pathname expansion (globbing) when calling external programs on Unix of necessity already does make this distinction:
E.g. printf '~' prints verbatim ~, and printf '*.txt' prints verbatim *.txt - only leaving these arguments unquoted triggers the emulation (as designed).
Similarly, printf '~/Documents' prints verbatim ~/Documents, whereas printf ~/'Documents'prints the equivalent of "$HOME/Documents" - note the of necessity partial quoting, which crucially leaves the ~/ prefix unquoted.
The point of this issue is that if the filename you're tab-completing happens to contain spaces, you end up with a broken command, because the completion quotes the whole argument and therefore deactivates tilde expansion.
(Fixing tab-completion alone isn't enough, however, because even a properly specified / completed argument with spaces, say printf ~/'Folder 1', currently does not trigger tilde expansion, even though it should - see #20754)
Even if it's restricted to native commands it still seems weird to me:
Why should I care if "printf" is a native PowerShell command or if it's a native command? PS usually does a good job of making it seamless but here I have to be aware of the type of command.
The point of this issue is that if the filename you're tab-completing happens to contain spaces, you end up with a broken command, because the completion quotes the whole argument and therefore deactivates tilde expansion.
Yeah I understand. Ironically, I did consider just using whatever quotes was used in the input string and just escape the spaces if the string was unquoted because it would be easier to implement but I ended up doing the quoting to match the old behavior.
Also, slightly fun fact: I don't actually use ~ myself, I just added that feature because it seemed simple enough to add and it allowed me add the scaffolding for later adding the variable replacement fix. Lesson learned I guess, even seemingly simple things like a shortcut/alias character can be surprisingly complex.
Yes, it is somewhat awkward from a PowerShell perspective, but it is unavoidable when worlds collide, as happens when a different shell's features are emulated.
The emulation - sensibly - only applies to external programs, given that PowerShell commands do their own expansion of ~ and wildcard patterns such as *.txt (where applicable).
If the quoting distinction weren't made, there'd be no way to pass a verbatim~ or ~/-prefixed argument to an external program.
I see that ~ expansion is now also coming to (calls to external programs) on Windows, as experimental feature PSNativeWindowsTildeExpansion, presumably first available in the next preview, which would be v7.5.0-preview.2
This means that - if it even ever becomes a stable feature - the first stable version it would land in is v7.5 - unfortunately, this is way too late as a fix for #20750
Activity
237dmitry commentedon Dec 5, 2023
Quoted part of path also does not work in pwsh with native utilities:
But works with object:
What
$freturns tocat, quoted Fullpath or space-escaped Fullpath?mklement0 commentedon Dec 5, 2023
237dmitry, yes that's the related bug linked to in the initial post (#20754).
Neither, because - unlike on Windows - there is no such a thing as a process command line on Unix-like platforms, only an array of verbatim arguments (in the case at hand, it is the value of
$f.ToString())MartinGC94 commentedon Feb 12, 2024
I understand that some (or all) Unix shells have this behavior so I can understand why people would want it to be consistent across the different shells. However, in my eyes the desired behavior seems a bit weird. To me a string is a string, it doesn't matter if you use single quotes, double quotes or no quotes at all, as long as you use whatever escape rules apply to the string type during assignment you are golden.
I can't think of any other example in PowerShell where a string is treated differently, depending on how it was quoted. Can you?
mklement0 commentedon Feb 12, 2024
MartinGC94, yes, the distinction should not and does not matter in PowerShell, but PowerShell's emulation of both the tilde expansion and pathname expansion (globbing) when calling external programs on Unix of necessity already does make this distinction:
E.g.
printf '~'prints verbatim~, andprintf '*.txt'prints verbatim*.txt- only leaving these arguments unquoted triggers the emulation (as designed).Similarly,
printf '~/Documents'prints verbatim~/Documents, whereasprintf ~/'Documents'prints the equivalent of"$HOME/Documents"- note the of necessity partial quoting, which crucially leaves the~/prefix unquoted.The point of this issue is that if the filename you're tab-completing happens to contain spaces, you end up with a broken command, because the completion quotes the whole argument and therefore deactivates tilde expansion.
(Fixing tab-completion alone isn't enough, however, because even a properly specified / completed argument with spaces, say
printf ~/'Folder 1', currently does not trigger tilde expansion, even though it should - see #20754)MartinGC94 commentedon Feb 12, 2024
Even if it's restricted to native commands it still seems weird to me:

Why should I care if "printf" is a native PowerShell command or if it's a native command? PS usually does a good job of making it seamless but here I have to be aware of the type of command.
Yeah I understand. Ironically, I did consider just using whatever quotes was used in the input string and just escape the spaces if the string was unquoted because it would be easier to implement but I ended up doing the quoting to match the old behavior.
Also, slightly fun fact: I don't actually use ~ myself, I just added that feature because it seemed simple enough to add and it allowed me add the scaffolding for later adding the variable replacement fix. Lesson learned I guess, even seemingly simple things like a shortcut/alias character can be surprisingly complex.
mklement0 commentedon Feb 12, 2024
Yes, it is somewhat awkward from a PowerShell perspective, but it is unavoidable when worlds collide, as happens when a different shell's features are emulated.
The emulation - sensibly - only applies to external programs, given that PowerShell commands do their own expansion of
~and wildcard patterns such as*.txt(where applicable).If the quoting distinction weren't made, there'd be no way to pass a verbatim
~or~/-prefixed argument to an external program.I see that
~expansion is now also coming to (calls to external programs) on Windows, as experimental featurePSNativeWindowsTildeExpansion, presumably first available in the next preview, which would be v7.5.0-preview.2This means that - if it even ever becomes a stable feature - the first stable version it would land in is v7.5 - unfortunately, this is way too late as a fix for #20750