Powershell: Provide a syntax to call native binaries when its name is aliased

Created on 20 Aug 2016  Â·  9Comments  Â·  Source: PowerShell/PowerShell

Like, if I have both gsn (as an alias) and gsn (as a script on Linux with Shebang), the latter one is unaccessable (unless you provide its full path).

Issue-Enhancement Up-for-Grabs WG-Engine

Most helpful comment

The ability to use ":gsn" was intentional. Per POSIX, any valid file name character can be used in a command name (where the legal filename characters varying between file systems).
With respect to @gsn, you can always use quoting to disambiguate e,g, Get-ChildItem "@gsn".
We do have an existing notation --% which tells parser to stop quote and expansion processing - we might be able to tweak that though it would be technically breaking but probably wouldn't really break anything, One other possibility is to simply keep using the .exe suffix syntax and give it the semantic that it looks for a native command without the suffix on *NIX systems e.g. 'gsn.exe' is mapped to "gsn"

All 9 comments

On Windows, it's common to use an extension, e.g. gsn.exe, but obviously that won't help on Linux.

A full path (or relative path) is the most obvious way to invoke an external command, but we do have a syntax (admittedly obscure) if you don't know the path:

& (Get-Command -CommandType Application gsn)

The & operator is the invocation operator - which is more often used to invoke commands with spaces in the path or to execute a command whose name is in a variable. In my example above, because of strong typing, the invocation operator recognizes the output of Get-Command (an instance of something deriving from System.Management.Automation.CommandInfo) and correctly calls that command, allowing you to override the default command resolution algorithm.

That said, I agree a better syntax is needed for Linux.

@lzybkr How about “:gsn”? I am not sure whether this prefix is occupied...

That would be a breaking change - admittedly unlikely to cause problems, but a breaking change nonetheless:

function :gsn { 'in gsn' }
:gsn

The above has worked since V1 - it likely wasn't intentional - I can't say for sure, I joined the team during V2.

@lzybkr So, according to your code adding any functions are breaking because... its name may be used in a user’s script.
These prefixed names are just “last-resort” binding, as a supplement of the existing variable resolution rules: when a name is not bound to anything else, try to find a native program with the same name.

What about @? It seems that you aren't allowed to call a function using @. Although it already have a meaning of splat operator. E.g. get-childitem @ls will now be ambiguous.

The ability to use ":gsn" was intentional. Per POSIX, any valid file name character can be used in a command name (where the legal filename characters varying between file systems).
With respect to @gsn, you can always use quoting to disambiguate e,g, Get-ChildItem "@gsn".
We do have an existing notation --% which tells parser to stop quote and expansion processing - we might be able to tweak that though it would be technically breaking but probably wouldn't really break anything, One other possibility is to simply keep using the .exe suffix syntax and give it the semantic that it looks for a native command without the suffix on *NIX systems e.g. 'gsn.exe' is mapped to "gsn"

Start-Process abc I guess this should work if you have proper file association, or Invoke-Item. If those are not available on PowerShell for *nix that's bad.

Probably something like this could do the trick even without language changes (we'll need to add only one new simple command and a convenience alias):

function Call-NativeCommand ($cmd) {
    & (Get-Command -CommandType Application $cmd) @args
}

New-Alias ^ Call-NativeCommand

After that you'll be able to do the following:

$ New-Alias curl echo # ensure that curl is an alias for something
$ curl --version # the alias got called
--version
$ ^ curl --version # the real binary got called
curl 7.28.1 (i386-pc-win32) [...]

Although I'm not sure how this will work with --% parser extension. Calling a native command with --% is probably a common use case, so we'll need to think about it.

Bash workarounds:
```
\ls
"ls"
'ls'
/usr/bin/ls
command ls
unalias ls; ls

Was this page helpful?
0 / 5 - 0 ratings