Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upCall native operator #13068
Call native operator #13068
Comments
|
I like the idea and find it useful, but think it would be far more useful (I'm thinking specifically in the case of a DSL) if I can get a single string expansion. So if I've built a cmd.exe compatible string in my PS, I have a way to string verbatim to cmd.exe. Perhaps
That would potentially also let me specify my interpreter:
in terms of the name/operator, is "&!" in use? That has similarity to shbang( "#!" ). |
|
The shell can be specified by simply specifying it as the command:
The $mycommand = "/bin/sh ls"
Invoke-Expression "&! $mycommand"However, in cases where you want to mix PowerShell with the native command, it's probably best to use the current syntax and just be aware of what needs to be escaped properly as I would consider that advanced usage. |
I can't believe you just suggested iex. :-) |
|
@essentialexch there are a few times where it's appropriate :) Note that in the example, expectation is that the user properly validated the contents of |
|
Great writeup and a solution for problems like the one you described are definitely needed. |
|
I agree
So this is the best way in case of conditional and whatnot for me |
|
@bergmeister I originally thought of |
|
@JustinGrote, there's no reason to not continue to use that. the |
|
Oh man, I remember having discussions with Bruce and Jason about this a decade ago. My gut feeling is that inventing another operator seems unnecessary here. I know that some people on this thread have not heard about # run ls in wsl, return results to powershell, then pipe to wsl again, to grep.
& wsl ls | wsl grep -i "foo"
# the entire pipeline right of wsl will run in wsl.
& --% wsl ls | grep -i "foo"Why hasn't anyone suggested this? It's logically consistent with usage of |
|
@oising well for one, that command doesn't work because you have to preface it with the command you want to run, are you suggesting adding the functionality? This kinda does what is expected:
|
|
@JustinGrote Yes, I know it doesn't work now :) I am suggesting that instead of I've expanded my example to show the differences. |
|
@oising I'd be cool with that over a new operator, though that is a lot of obtuse typing for "new powershell user who knows bash" which is what I assume this would be meant for. |
Not at all. It's for the PowerShell user that doesn't understand the complex quoting rules between PowerShell/cmd.exe/bash. As the issue title says "call native", for calling native executables. |
True, or for those of us who'd rather not have to think about them at all. |
|
Yeah I'm with @oising. This concept exists, it's just woefully insufficient. If we're going to implement something completely new we're better off deprecating/removing the old syntax. I feel oftentimes these ideas are voiced, not enough weight is given to their actual target demographic. If users are already struggling to find the existing methods, and finding the existing methods lacking when they are found, it's a call to a) improve documentation, and b) improve the actual functionality of the existing operators. Instead we get a weird option c) which is supposed to somehow address the past issues whilst introducing yet another operator which is relying on documentation which is already not accessible enough for users to find it naturally. I agree that error messages and/or the suggestions system should be used to help introduce these concepts. I don't agree that we need a third? fourth? fifth? (I've literally lost count, someone help me out here) way to invoke commands. The existing methods are insufficient -- that means we should improve them, not leave them behind like cobwebs to confuse users further when they start digging into them. The first question I tend to get when people realise there's 5 ways of doing something is "why are there 2-3 ways that literally do the same thing but don't work as well", and my answer is as it always has been -- the PS team is way too focused on making sure everything from the past decade++ still works, when trying to add/improve functionality. Here we see it again, we have existing but insufficient implementations that need revision and improvement, and the solution proposed is to further muddy the pool by adding another potentially incomplete implementation. We should be finishing what we start, not starting another implementation all over again, IMO. |
|
I believe if we are going to be using & for more than a few Unique use cases we should start thinking about making this considered a verb or look at standardization across the language. The last thing I would want is confusion about what & is meant to do. In its entirety. |
|
I'd consider 3 scenarios:
I wonder where @mklement0 comments? :-) |
|
At start of reading this thread I thought; great idea! But after reading comments it started me thinking. I have always found the & command 'not PS standards worthy" and something reminding me of 'PERL days' (ugh). Introducing another non-standard PS command (not being noun-verb) will not help. Certainly not those less savvy at PS. I did not know about the --% parameter either. I use the same principle as @JustinGrote as a solution. Cutting/pasting commands into PS shell has never been my main 'thing'. I vote for exploring improving existing commands. And - indeed - improving some documentation on --% and & usage @iSazonov the use case @SteveL-MSFT is proposing is the 'cut paste' scenario. Partial expansion would make things much more difficult I think (on the AST side of things) |
|
Immediately though of “#!” and then “!#”. Liking the “&!”. |
|
We can probably look at adding token accelerators to function calls in the tokenizer. This would allow for the use of the following. Iex -l I feel adding more unique tokens at the parsing level makes the barrier to entry go up and discoverability for this feature goes down. Get-Help & for example doesn't show up with anything. And we have to look for it in about_Operators. However there are unique cases for the call_operator that doesn't get documented. I believe whatever is decided on it needs to fully take into account how discoverable this "feature" is, from a new user perspective and keep in mind that newer users will try to use this on Powershell 5 not without knowing its new to pwsh core if the discoverability is too low. |
|
I'd love us to change the existing behaviour, but changing such a fundamental API in PowerShell would just break so many things. We could possibly consider migrating over with a configuration. Breaking things more directly might once have been possible before PS 6 went GA, but honestly, even then it would have been a serious threat to backward compatibility (not unlike Python's In terms of passing arguments to subprocesses, I think both synchronous invocation and For synchronous invocation with cmdline arg passing, I see four kinds of argument passing possible:
I think the first behaviour should be slowly phased out by introducing the second as an experimental feature and then swapping them. The second and third behaviours could have their own sigils like |
|
If the request is only to address copy-paste scenario like "Any text content after this operator will call into the "default shell" of the OS to execute." why do not say this explicitly by
|
|
I absolutely don't see how this would resolve #1995: See #1995 (comment) Also, the problem with WSL is a problem of the behavior of Oh, and isn't this almost a duplicate of #12975 ? Because I can essentially mostly repeat, what I mentioned there: @bitcrazedThe problem is that the lack of an ability to delimit a portion of a command-line to be passed varbatim to the receiving command/script is something that trips users up all the time. The only thing regarding "portion of a command-line to be passed varbatim to the receiving command/script", that would be improved with this operator would be meaning (2.) above, and as mentioned, I think developing in that direction is bad. If all you want to do is a shortcut do copy&paste existing command lines, why don't you add a cmdlet (e.g.
If it must be one line, then add one-line-here-string syntax, but please don't implement a special operator, that can't be properly found and just complicates everything. And please don't abandon #1995 for this! |
|
@SP3269, we can cross that bridge when we get to it But seriously: If you think of "native" as "written specifically for the host platform [family]", the name would still fit, even if PowerShell should ever become the default system shell on a given platform (here's hoping, but I don't think that's realistic, at least not in the foreseeable future). As for alternatives:
|
|
I think I am beginning to unravel the utter confusion I'm experiencing trying to keep track of everyone's motives, ideas and issues here. It seems that we're (@mklement0 and I, at least) are looking at this as two different solutions to two different views of the same conceptual problem. What I was suggesting was using
This point I don't get at all. It's no more lacking a closing delimiter than ins/invoke-nativecommand is. If you need to delimit or feed from the LHS, use here-strings, else it is considered as a single statement. |
|
Regardless of whatever way is chosen, it seems that there will be a need to choose a native shell to dispatch the commandline. I suggest we use the environment variables |
Basically you can't call things like |
No: the system shell on Unix-like platforms is invariably
Good point, that's the better way to refer to the system shell (command interpreter) on Windows - I've updated the sample command above accordingly. |
We have |
|
I've seen that. How exactly would you combine |
Yes, I understand the current behaviour @vexx32 . But we're not (at least I'm not) talking about the current behaviour of As I said way, way up above, we could enhance |
So the current pitch for adjusting |
Currently it will be |
|
I think the thing should be equivalent to making an executable script file and running it, which delegates the task of choosing the right shell to the operating system and we should not be bothered. Including, if it starts with |
|
The idea behind
To address the latter as a courtesy (so that users don't have to write their own aux. batch files), for conceptual clarity, we could offer an That said, if there is consensus that the majority of public |
|
To me, the integration-of-native-errors RFC you link to is worth addressing just as urgently as #1995: Both represent necessary steps toward making external programs (native utilities) first-class citizens in PowerShell (as much as conceptually possible), which they should always have been. Being a first-class citizen means: direct invocation (with (As an aside: Therefore, Then the mechanism proposed in the RFC will act on it, as it would act on directly invoked executables (e.g., if (A quick aside - this discussion doesn't belong here: As for a per-call mechanism: something like |
That is not what I wanted to say. I wanted to say that PowerShell does not need to know what the default shell is because operating systems have this feature built in. Linux knows how to execute an executable script in case it does not start with |
|
Again, With respect to robustly determining the system shell, there is no problem to solve here: hard-coding No, Unix platforms at the system-call level do not know how to execute an executable plain-text file without a shebang line; that you still can invoke such files is a convenience feature of POSIX-like shells: they try Needless to say, it is therefore ill-advised to create such scripts. |
|
|
I hope it is obvious that this makes my point: it's up to each shell to decide what to do, and different shells / scripting languages do different things; PowerShell currently just fails - if it had to make a choice, and you wanted that choice to be |
|
Maybe it is just me, but I would trade a thousand |
That can not be true if it works with scripts without
Edit: I just noticed, that if you use the library function
However this is not a feature of "linux" but of the gnu c library - and again according to the man page it uses explicitly /bin/sh and not some userdefinable shell. (Hardcoded in the source of |
Since it comes from |
Oh lordy... Is everyone just trying to troll me? Anyway, I don't have any skin in this game and I think I've said enough. I still think there's something seriously wrong about using a cmdlet to defer to another shell from within a shell. It's just clumsy. It's especially clumsy when you're using a cmdlet to execute another shell to execute a native command that has no need for that secondary shell in the first place. The whole thing just smells bad. edit: last word The title of this item is "call native operator." I see a wasted opportunity when we already have a call operator |
The point of the operator is that it doesn't parse literally any PowerShell syntax. There's no such thing as here-strings. There's no such thing as single quoted string constants. It's "send the text to the right as is" not "evaluate the expression to the right, convert to string and send it's value" So for example, if you had this: --% @'
echo my native command
'@it would translate to: cmd.exe /c "@'"
echo my native command
'@Except you'd get a parser error because I think maybe you're picturing the implementation differently so that it's more or less the same thing as the pitch for Also worth noting that this is how the existing functionality works as well. This example works mostly the same way: cmd /c --% @'
echo my native command
'@ |
|
I repeat:
Let me spell it out even clearer: Allow here-strings to follow |
|
Hah that's a big oof - yeah I missed that, sorry @oising. About that idea I think it would be a little confusing to have |
|
Thanks for digging deeper re There is no system (or library) function called
As stated, for direct execution the major POSIX-like shells ( Since on Unix the use of a script file behind the scenes is unnecessary, we can make the same assumptions about the system shell path as the fallback library functions, and I recommend Despite the POSIX spec not mandating the location of
The same risk applies to locating |
Normally you say |
The only reason to target an executable named |
There is no way to limit a Web search to user scripts, especially since many user scripts are not marked executable at all, and even if they are, they may rely on |

Problem Statement
Currently, there are cases where cutting and pasting a native command line fails to run as expected in PowerShell. This may be due to incorrect parsing of quotes meant to be passed to the native command or use of PowerShell syntax that is not meant to be interpreted as PowerShell. PowerShell has a
--%special argument when used with native commands treats the rest of the arguments as literals passed to the native command, but has several issues:|,&&, and||take precedence, so:wsl --% ls | lesswould executewsl lsand pipe the results tolessrunning in PowerShell rather thanlessrunning in wsl--%towards the beginningProposed technical implementation details
Proposal is to introduce a new
--%(Call Native) operator.Any text content after this operator will call into the "default shell" of the OS to execute. On Windows, this would be cmd.exe and on Unix-based systems this would be /bin/sh. This resolves the globbing issue on Unix-based systems, and also allow
%variable%expansion on Windows. Unlike--%switch, this also means that|,&&, and||are treated as part of the native command line.This means that these two are functionally the same:
where
$fooand$PWDis evaluated by the shell within WSL. Note that in the first example, you would have to know to escape&&to have it execute within WSL instead of within PowerShell.To pipe output from such execution back into PowerShell, the user is required to store the results into a variable first:
Note that unlike the current
&call operator, you cannot use any PowerShell syntax, so:would not resolve
$commandlineas a variable first by PowerShell, but instead pass$commandlineto the default shell to process unresolved.The cut & paste problem is solved by simply pasting after
--%is typed.The above example for wsl would look like:
where the intent is to have that whole line execute within the WSL Linux instance.
Discoverability
Users already familiar with
--%as a switch may easily transition to using this new operator where it makes sense. For new users,--%is unique so that search engines find it easily related to PowerShell.Alternate Considerations
&!and&nwere proposed as the sigil, but there was push back because&!is a valid operator in some languages making a web search for documentation more difficult. There was also a concern whether visual similar to&call operator would be confusing to users.There is question about supporting line-continuation when using this new operator. I would suggest that we do not support it initially.
A cmdlet solution instead of an operator solution was proposed. We believe this doesn't solve the "cut & paste" problem as now you need to know to put the pipeline in single quotes and/or escape special characters. We do believe a cmdlet as in
Invoke-NativeCommand(noun to be determined) would be useful as an additional option instead of replacing the need for an operator.Related issues
This should also solve these issues:
#1995
#12491
#1761