-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Command line arguments with a dollar sign #4024
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I believe this is by design. Solution is to use the backtick to escape:
|
I'm not sure it's by design. Compare:
Notice in 1, 2, and 3, I would say we need some more digging before calling this by design - but it does provide a cleaner workaround - use |
To summarize the difference in behavior:
In the case at hand:
|
Getting -File for .ps1 and -Command to parse args the same as -Command (so that variables are string literals) is working. Need to figure out how to get scripts without .ps1 extension to work. With the change I'm proposing, "Before$After" needs to escape the $ otherwise expectation is that PowerShell interprets it as the value of the $After variable. |
@SteveL-MSFT: I think it's vital that we align the behavior of
In other words: what follows an ad-hoc script (
Conversely, anything that should be interpreted according to PowerShell-internal rules, must go directly into the ad-hoc script passed to To illustrate the proposed difference: # Already works this way.
> powershell -noprofile -command '"$HOME"'
/home/jdoe
# This is how it *should* work (currently breaks).
> powershell -noprofile -command '$args' '$HOME'
$HOME |
@PowerShell/powershell-committee reviewed this and although we agree the argument handling isn't technically correct, it has been this way since inception and would be a big breaking change without significant benefit, so the current behavior is 'by design'. |
Thanks for letting me know, @SteveL-MSFT. I sincerely wish you revisited this issue, however: While I get that breaking changes are very problematic, I think:
Consider the following calling-from- # Breaks, because literal `don't` is interpreted as a bareword by PowerShell.
$ powershell -noprofile -command Write-Output "don't" # !! BREAKS
The string is missing the terminator: '.
#'# With a *literal*, you can work around that, but in addition to the
# outer quoting - WHICH SHOULD BE ENOUGH - it requires TWO EXTRA LAYERS OF
# QUOTING: 1 for bash (\`) and 1 for PowerShell (the ` passed through).
$ powershell -noprofile -command Write-Output "don\`'t" # works, but extremely cumbersome.
don't
#'# Using a NOT-KNOWN-IN-ADVANCE VALUE is SIMILARLY CUMBERSOME AND COMPLEX:
$ v="don't"; powershell -noprofile -command Write-Output "'${v//\'/\'\'}'" # works, but extremely cumbersome.
don't Cramming it into the first argument is an option, but equally cumbersome: $ powershell -noprofile -command "Write-Output \"don't\""
don't
$ v="don't"; powershell -noprofile -command "Write-Output '${v//\'/\'\'}'"
don't PowerShell's current reassemble-all-arguments-into-a-command-line-and-then-reinterpret-it approach severely hampers the ability to pass arguments as-is, as data to the command. Interpretation as PS source code should be limited to the first argument - the "mini-script". Separately (as previously stated), so as to align with POSIX-like shells, the remaining arguments should be passed via # WISHFUL THINKING; note how $v is passes via $Args
$ v="don't"; powershell -command 'Write-Output $Args[0]' "$v"
don't |
@mklement0 as part of the fix for the other related issue #4036 I intend to also make a doc update to hopefully clarify this for the user on the differences between |
@SteveL-MSFT: I'm glad to hear it's getting documented.
Undoubtedly.
Just be aware that you're closing the door on allowing
Absolutely, that's a must in any scenario. But requiring double escaping for things that should be passed as literals (e.g., To repeat myself briefly, interpreting individual arguments passed to a command as part of the command's source code subverts fundamental notions of how arguments are passed in the Unix world. The saving grace is perhaps that wanting to pass literal data arguments to a single command string that functions as an ad-hoc script is not that common (e.g., In the absence of passing such arguments, if the current behavior is retained, I suggest documenting that the best use of $ powershell -noprofile -command 'Write-Output' '`$HOME' # confusing: 2 args using: $ powershell -noprofile -command 'Write-Output `$HOME' # better: 1 arg |
Cc @BrucePay |
When it comes to documenting the current behavior of
|
@mklement0 please take a look at my PR for the doc update and add any suggestions on language MicrosoftDocs/PowerShell-Docs#1430 |
Thank you, @SteveL-MSFT. To [half-mis-]quote Dame Edna, I mean the following in a caring way:
Truthfully, I think PowerShell's documentation needs a serious overhaul, and my potential contribution to this particular help topic would feel like rearranging the deck chairs on the Titanic. |
@mklement0 I don't think you should feel like you are constrained to the style that exists in the current docs. They were written years ago. I prefer to avoid a lot of detail as I feel people tend not to read that much content. I'd rather add more examples that show the differences. If you have thoughts on some specific ones, please share :) |
@SteveL-MSFT: I appreciate the invitation, but it feels overwhelming to me. A few more meta observations:
|
Command line arguments sent to a file do not send in full if the argument contains a dollar sign. I have tried every combination of escape character and quote configuration that I can think of. I am not certain if this is specific to the dollar sign but I was able to use single quotes with an exclamation mark in the argument and that worked fine.
I was not able to find any explanation for this in other open issues or the known issues but I apologize if I'm missing something obvious here.
Steps to reproduce
Create a new ps1 file called test.ps1 with this snippet.
Then calling it from the command line
Expected behavior
Actual behavior
Environment data
The text was updated successfully, but these errors were encountered: