Hacker News new | past | comments | ask | show | jobs | submit login

It's funny how the article claims that treating everything like a string is a drawback, when it's often touted as a strength of bash.

The author of this piece claims: "Powershell [...] offers a series of commands useful for developing tools and automatisms that are very difficult to implement with simple strings." but as far as I can tell, they don't go on to actually explain any of these cases where Powershell is a more appropriate tool than traditional string-based shells.




Let me channel Snover really quick:

Imagine you need to get the MAC address of a network adapter in Bash. One way to do it would be...

   ifconfig eth0 | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'
...another...

   ifconfig eth0 | awk '/^[a-z]/ { iface=$1; mac=$NF; next } /inet addr:/ { print iface, mac }'
Both of these are tied to the way the MAC address is printed in the output of the ifconfig command, and there's no contract that says that can't change. In fact, there are probably versions of it out there where these won't work. In PowerShell you would do this...

    Get-NetAdapter -Name Wi-Fi | select -ExpandProperty MacAddress
This is far more readable if you pass this script on to someone else, it won't break if the way it Get-NetAdapter gets rendered to the screen changes, and best of all, since I know the discoverability tricks in PowerShell, even though I've never done this before, I didn't have to go to stack overflow to find it.


Right, but the fact that you can parse out something that didn't have a contract is a strength.

Someone had to write the Get-NetAdapter cmdlet to give you a contract, and Linux has those too, so a fairer comparison would be something like:

    addr=$(</sys/class/net/ens33/address)
I think that's just as readable as your example.

The question is how does powershell handle extracting something without a contract, and is that more readable than bash? I'm skeptical :)


> "Someone had to write the Get-NetAdapter cmdlet"

Amusingly no, nobody wrote it. There's a part of PowerShell which can wrap WMI/CIM classes into auto-generated cmdlets, and Get-NetAdapter is one of those. (Which is why it's not available on Linux installs of PowerShell).

Take a look at the XML in C:\Windows\System32\WindowsPowerShell\v1.0\Modules\NetAdapter\ and there's no C# code or .Net DLL for it, just "MSFT_NetAdapter.cmdletDefinition.cdxml" and "MSFT_NetAdapter.Format.ps1xml". Presumably auto-generated, human checked, though I can't prove that.

[1] https://docs.microsoft.com/en-us/previous-versions/windows/d...


Its not like pwsh can't do strings ffs. It just can do objects on top of that. You can totally go bash-like-crazy in it and parse strings if you like that.


Sure, I'm saying that would be a fairer comparison - getting output from something that has no defined interface.

So why not compare apples to apples, how would powershell extract the MAC from ifconfig output? If that's more flexible or powerful than bash with standard UNIX tools, then that might be impressive!


> how would powershell extract the MAC from ifconfig output?

It could go identically crazy as in bash, as it has its own grep (sls), can use grep itself etc.

    > (ipconfig /all | sls Physical) -replace ".+: "
    00-FF-84-14-66-D7
    00-FF-B7-06-19-0F
    00-15-5D-00-1F-3C
    ...


Right, that's a fairer comparison. So the question is, why is that better?


Its not. Everything else is.

Although, on more thought, it is better even as parsing engine as you have system design rules enforced across tools and OSes. Even single tool may work differently depending on *nix flavor.


Here's what I got:

ifconfig | ?{$_ -like "eth0 *"} | %{($_ -Split " ")[-1]}

In other words, find the line that starts with "eth0 ", then return the last column using " " as a delimiter.


But Get-NetAdapter just works. Your command, I don't have a /sys/class/net/ens33 on this Ubuntu virtual server. I do have a /sys/class/net/venet0 but /sys/class/net/venet0/address is blank, even though the VM does have an IP address.

Grepping everything under /sys/class/net/* can't find the IP in there. It shows up in `ip addr` as venet0:0 and as a P-t-P link, so I assume that's related; doesn't work unless you know the adapter name and still might not work then? What kind of "contract" is that?


Here's the output of the command the parent told me to run on my Windows workstation:

    > Get-NetAdapter -Name Wi-Fi | select -ExpandProperty MacAddress
    Get-NetAdapter : No MSFT_NetAdapter objects found with property 'Name' equal to 'Wi-Fi'.  Verify the value of the property and retry.                                                          
    At line:1 char:1                                                                              
    + Get-NetAdapter -Name Wi-Fi | select -ExpandProperty MacAddress                              
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~                                                                  
        + CategoryInfo          : ObjectNotFound: (Wi-Fi:String) [Get-NetAdapter], CimJobException
        + FullyQualifiedErrorId : CmdletizationQuery_NotFound_Name,Get-NetAdapter               
I know the problem, I don't have a wireless card on this machine, but how is this different from you complaining that your network interface isn't called ens33?


Even better than the ip | jq in my sibling comment.


Your example is relevant to show how powershell can handle some tasks better, but this task is better performed with ip than ifconfig, as it has an option for json output which jq can parse:

  ip --json link show eth0 | jq '.[0].address'
I'll admit that the discovery of this is probably not very great. I wouldn't be surprised if a number of people learned about the json output, and possibly jq, from this post.


PowerShell is simply inverting the defaults: Linux/Bash scripts output formatted text by default, but sometimes have options to return objects (often as JSON text strings). PowerShell cmdlets by default return objects (in a custom binary/in-memory format, but convertible to/from JSON, among other options like CSV and XML), but might optionally return formatted strings. (PowerShell also offers tools out of the box similar to but different from jq for exploring/converting/navigating objects.)

In general when working in PowerShell you don't have to look up if there is a command with a --json flag (or equivalent) that does what you need to do, you can assume that objects are the default response and move on to working with them with PowerShell's jq equivalents. (Obviously, that makes discovery generally easy.)


Now parse the IP address


  ip --json address show eth0 | jq '.[0].addr_info [].local'


Cherry picking. Not a system feature. Good luck with that in general.


I'm not on a Linux box at the moment but isn't there an eth0 entry in /sys (or maybe /proc) which can give you mac address in easier to parse way (I think you could just use cat).

I don't know if they are still in vogue but /sys and /proc interfaces were originally intended to return clean output which is easy to parse in programs and scripts. I guess usage never really caught on.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: