Powershell: Re-Implement UNIX aliases as a typed, parameter-to-parameter compatible version of the original UNIX native app

Created on 4 Sep 2016  ·  8Comments  ·  Source: PowerShell/PowerShell

like, ls would be a cmdlet accepting a parameter called al, and produces a full list while its output result is typed.

Area-Cmdlets Issue-Enhancement OS-Linux OS-macOS Up-for-Grabs WG-DevEx-Portability

Most helpful comment

The basic idea sounds like a great open source module side-project, but not something that should _ever_ be done as part of Core PowerShell.

It would be a huge amount of work (and most of it would be wasted). These so-called "original" apps have almost 50 years of evolution ... with lots of redundant options and conflicting parameter sets, most of which are rarely if ever used.

For example, the _simple_ command ls has over 50 parameters, from -a and -A (which can't be used together) to -x and -X (which have nothing to do with each other) and -Z (which _must_ be upper case). On top of that, it responds to environment variables...

However, more importantly, it can't really be done, because the _parameter syntax_ of Unix native commands simply _isn't supported_ in PowerShell.

  • --double-dash-parameter names aren't really valid
  • smashing together of individual letter flags does not work
  • case-sensitive flags aren't valid
  • --parameter=value isn't valid (PowerShell uses -parameter:value)

PowerShell currently sort-of allows those things when you're passing parameters to a native executable, but it certainly does not allow them with native PowerShell scripts or cmdlets. Even if the PowerShell team decided to allow case-sensitive aliases on PowerShell commands, you would still have to accept using ":" instead of "=" for parameter values, and to give up on smashing flag parameters together -- which would mean that the muscle-memory things would just not work.

But even if you were ok with that, you still can't do it:

First you'd have to choose between divergent versions of the commands and parameters available across the Linux ecosystem. E.g. GNU vs BSD. As a simple example, consider the command ls where the -F and -G flags involve color on BSD, but append indicators and group output on GNU (where --color is used for color).

Then you would have to invent all sorts of formatting hacks (like attaching pseudo-types to output to select different formatting rules), since unix native apps each do their own formatting and sorting -- most of the parameters to a simple command like ls are actually concerned with the formatting or sorting of the output.

And after all of that, it just wouldn't be cut-and-paste compatible because of the lack of support for smashing flags together, and colons in parameters, but most importantly, because native apps _stream text,_ and these would stream objects, so anything you _used to do_ that involved more than one command in a pipeline would probably fail with these new commands.

Please just learn to use PowerShell syntax

There is a ton of functionality that would be awesome to add to PowerShell -- this isn't it. Spending valuable development time trying to cobble together something to make it feel more like bash is a sad waste of effort.

All 8 comments

Hmmm perhaps we want to check out if any param name collides.

@GeeLaw Maybe an alternative parameter parser in getopt flavor?

The basic idea sounds like a great open source module side-project, but not something that should _ever_ be done as part of Core PowerShell.

It would be a huge amount of work (and most of it would be wasted). These so-called "original" apps have almost 50 years of evolution ... with lots of redundant options and conflicting parameter sets, most of which are rarely if ever used.

For example, the _simple_ command ls has over 50 parameters, from -a and -A (which can't be used together) to -x and -X (which have nothing to do with each other) and -Z (which _must_ be upper case). On top of that, it responds to environment variables...

However, more importantly, it can't really be done, because the _parameter syntax_ of Unix native commands simply _isn't supported_ in PowerShell.

  • --double-dash-parameter names aren't really valid
  • smashing together of individual letter flags does not work
  • case-sensitive flags aren't valid
  • --parameter=value isn't valid (PowerShell uses -parameter:value)

PowerShell currently sort-of allows those things when you're passing parameters to a native executable, but it certainly does not allow them with native PowerShell scripts or cmdlets. Even if the PowerShell team decided to allow case-sensitive aliases on PowerShell commands, you would still have to accept using ":" instead of "=" for parameter values, and to give up on smashing flag parameters together -- which would mean that the muscle-memory things would just not work.

But even if you were ok with that, you still can't do it:

First you'd have to choose between divergent versions of the commands and parameters available across the Linux ecosystem. E.g. GNU vs BSD. As a simple example, consider the command ls where the -F and -G flags involve color on BSD, but append indicators and group output on GNU (where --color is used for color).

Then you would have to invent all sorts of formatting hacks (like attaching pseudo-types to output to select different formatting rules), since unix native apps each do their own formatting and sorting -- most of the parameters to a simple command like ls are actually concerned with the formatting or sorting of the output.

And after all of that, it just wouldn't be cut-and-paste compatible because of the lack of support for smashing flags together, and colons in parameters, but most importantly, because native apps _stream text,_ and these would stream objects, so anything you _used to do_ that involved more than one command in a pipeline would probably fail with these new commands.

Please just learn to use PowerShell syntax

There is a ton of functionality that would be awesome to add to PowerShell -- this isn't it. Spending valuable development time trying to cobble together something to make it feel more like bash is a sad waste of effort.

@Jaykul @GeeLaw Or maybe a “parser” on the PS-Native barrier?
Hmm it will be related to #1908 now.

An example scenario:

ls | % {echo %_.Length } # Returns file size
#  ↑ do something here
#    like: parse the `ls`'s output and return a typed wrapper
ls | ls-to-ps-parser | % {echo %_.Length } # Returns file size
#  ↑ more verbose?
ls | as-text | % {echo %_.Length } # Returns length of each line

@be5invis @Jaykul didn't even think about param style problem... If that problem is overcome, it is not very hard to invent a shim cmdlet, called ls, to mimic ls. I.e., make ls dedicated for UNIX style usage, not an alias for `Get-Child-Item‘. This breaks Windows PowerShell but is good as a long run.

But the param style is not easy to deal with -- it increases hardness for new users.

To solve the problem inside current implementation of PS, we could create a cmdlet Use-Unix that accepts appropriate parameters, then calls the native utility, and finally parses the output according the the utility used.


Edited 12:26 PM 6 September 2016 (UTC+8):

And it sounds impossible to just ls | % { echo $_.Length }, since it's impossible for PowerShell to figure out the first command is ls, unless that ls refers to a PowerShell cmdlet instead of a native utility. There must be something that tells PowerShell to parse the output as if it is an output from ls native utility.

The philosophy of Unix commands is different from PS cmdlets and there are several parameters involving formatting the output in a typical Unix command. For example, -lFh for ls. In PS, formatting is done by applying Format-... cmdlets and other operations to objects before sending them to Out-... cmdlets. It sounds like Invoke-Cmdlet | Out-String | Parse-CmdletOutputStringIntoOutputObjects.

At least, formatting parameters should be ignored when having a PS wrapper.

@GeeLaw What if you alias ls to a function (or even an external application if RFC0005 is accepted) which strips formatting parameters, and do the format on itself when necessary?

@be5invis Yup, that's stated as "formatting parameters should be ignored when having a PS wrapper". But still, internal commands cannot easily workaround the param style problem.

@GeeLaw I'm with @Jaykul on this one. I too think that the effort is not worth it. The muscle memory is easier to rewire, than to keep it but also keep in mind the subtle differences, such as stream of text vs. stream of objects. Any time you used to pipe the result of ls -al (which in itself is very hard to make work) to another command, you have to take a different route.

ps -aux | grep username

works on Linux systems but what happens one you ported both ps and grep? The latter will expect input as a stream of bytes, but ps already provides objects. In short: hell breaks loose.

IMHO it's infinitely more useful to simply embrace PS for what it is, rewire muscle memory to non-*nix-overlapping aliases like gci et al. I went down this road, after 2-3 months of use I got to a point where I was dropped into a bash shell I have felt at home for the past 10 years I saw this:

mnagy@MATTY-GL702ZC:~$ gci
No command 'gci' found, did you mean:
 Command 'gcx' from package 'gcx' (universe)
 Command 'sci' from package 'scheme2c' (universe)
 Command 'gsi' from package 'gambc' (universe)
 Command 'gcp' from package 'gcp' (universe)
 Command 'gcin' from package 'gcin' (universe)
 Command 'gcc' from package 'gcc' (main)
 Command 'gcv' from package 'scotch' (universe)
 Command 'gcl' from package 'gcl' (universe)
 Command 'ghci' from package 'ghc' (universe)
 Command 'gc' from package 'graphviz' (main)
 Command 'gco' from package 'gco' (universe)
 Command 'gcj' from package 'gcj-jdk' (universe)
 Command 'ci' from package 'rcs' (universe)
 Command 'gcb' from package 'gcb' (universe)
 Command 'gri' from package 'gri' (universe)
gci: command not found

I could also quote a dance teacher of mine:

Either do, or don't do, but sort-of doing looks the worst.

Was this page helpful?
0 / 5 - 0 ratings