a rising tide lifts all ships but bash is the mooring block.
a rising tide lifts all ships but bash is the mooring block.
If I were doing stuff with Windows registries, I might use PowerShell, but I don't. I use Unix.
One is not a substitute for the other -- it's both the language AND the "bindings" that count. bash runs on Windows, and PowerShell runs on Linux, but you lose a lot of "enviroment" in both cases.
I wrote about this distinction here - https://www.oilshell.org/blog/2023/06/ysh-design.html - Oils Is Exterior-First (Code, Text, and Structured Data)
In those terms, I say PowerShell/nushell are "interior-first", while bash and OSH/YSH are "exterior-first". It makes a big difference when using them.
pwsh reinforces pretty much the same* thing every time it's used, the more you learn the more you can do with every command, even ones you haven't used yet.
same subject to some base-level provided by the module. i.e. the active directory cmdlets have their own dsl inside -filter because it is a different thing. It's very analogous to `a = sql.cmd('SELECT ...').map(etc...)`. you can, you shouldn't, but maybe its fine. It's up to you.
trying nushell next, it looks very promising.
- Jeffrey Snover, Powershell Inventor.
https://evrone.com/blog/jeffrey-snover-interview
Literally designed not to copy bash.
The Get-Help command is super useful, with the option to show examples (-Examples).
Consistency is encouraged because every PowerShell command is the combination of a verb and a noun. The verbs are standardised and you can get a list of supported verbs using Get-Verb. Nouns are free to choose.
There is also Get-Command which gives you a list of available commands in your current shell. You can import modules in the shell which will give you access to extra commands. Get-Command supports the parameters Module, Verb and Noun to filter commands. This allows you to fairly easily discover commands that might be usefull to you.
The Get-Alias command will show you what aliases are defined in your shell. This can sometimes be confusing as some of the default aliases look like Linux/UNIX shell commands.
Creating a PowerShell module is also not that hard. When defining a PowerShell command, it is for example very easy to limit the values for a certain parameter and that in turn hooks in into the completion functionality. The completion functionality is available out-of-the-box for every PowerShell command available, including the ones that you create yourself.
My main OS is Linux, but I do work a lot with Windows systems (I develop in C#). I've used bash a lot, but I also learned PowerShell because that is simply the way to go on Windows systems. I like PowerShell, it has a lot of nice features and it is easy to work with. I find it a lot easier to program extra functionality in a PowerShell module compared to defining extra functions in bash. As a C# developer, PowerShell basically also gives me access to any C# class available by default in .NET. It is even simple to load a class from a third-party assembly, and even to compile C# code on the fly. In short, I can do whatever I want in PowerShell a lot easier than in Bash.
Note that that does not mean that I no longer use Bash. It depends. My default shell on linux is bash. When I need a one-liner to do something, I will first reach for bash. It is only when I need a longer script that I will reach for PowerShell. For example, I need to read a json file, manipulate the json structures and write the data back out. That is something I would do in PowerShell. For a build script that is simply a sequence of steps, I would go for bash, even if it involves the use of jq for json for example. And obviously on Windows, my default shell is PowerShell. Even though I have used cygwin/ming before, I would not do that if I can avoid it... there is really no need to try to run bash or anything else on Windows when you have PowerShell.
In the case of ksh88, it was able to be compiled into a 64k text segment which was the maximum allowed on Microsoft XENIX running on an 80286.
This is a place that Powershell cannot go.
$ echo 25 | pwsh -c '$input-replace"\d",{2*"$_"}'
410
$ echo 25 | perl -pe 's/\d/2*$&/eg'
410
``` PS> $temp:pwsh_out = 10000
PS> /bin/cat /tmp/pwsh_out
10000
``` $ echo ''''
PS> echo ''''
'
``` PS> $Y = { param($f) . { param($x) . $x $x } { param($y) . $f { param($x) . (. $y $y) $x }.GetNewClosure() }.GetNewClosure() }
PS> $fac = & $Y { param($f) { param($n) $n -lt 2 ? 1 : $n * (. $f ($n - 1)) }.GetNewClosure() }
PS> & $fac 5
120
``` PS> gv -v|% m*d|% t*
gv -v|% m*d|% t*
PS> &($x={"&(`$x={$x})"})
&($x={"&(`$x={$x})"})
$ bash
$ eval ${x='echo eval \${${x@A}}'}
eval ${x='echo eval \${${x@A}}'}
```bilingual pun,
.ps1 .pl
1 1
{1} {1}
end {1} sub {1}
{end {1}} {sub {1}}
&{end {1}} &{sub {1}}
``` awk -e 'BEGIN { printf "3\n" }'
perl -e 'BEGIN { printf "3\n" }'
ruby -e 'BEGIN { printf "3\n" }'
pwsh -c 'BEGIN { printf "3\n" }'
``` $ time ...; time ...; ....
real 0.00 ...
real 0.00 ...
real 0.03 ...
real 0.22 ...I think there will always be a place for something like bash pipelines, where the handoff is just a bunch of bits. Some work is all about discovering the structure of your data: you can't have tools that already know it.
But that's not the majority of work these days. Having the handoff be just bits is an elegant solution to the tower-of-babel problem, but it would probably be ok if we spent more time in structured-mode and only leaned into that solution when it was specifically called for.
The problem is that there's no intrinsic structure to data, just useful fictions. This makes structured-mode necessarily opinionated, which means that the ecosystem will always be fragmented: bash and zsh are friends. Powershell and nushell are rivals.
This means it's either
- Some "Open Core" bullshit with the secret sauce conveniently tucked away in some proprietary blob or restrictive license submodule
- Has a build process so convoluted and mystery-meat-dependency filled it's not worth to bother with.
- Has so many anti features it would require an extensive patchset (like ungoogled-chromium) to fix.
So it might be interesting technology, but it's not something I'd deploy by default to every server and expect to work in 5 years time.
Oh, heh, also https://github.com/PowerShell/PowerShell/blob/master/docs/bu... the build script is written in PowerShell, so there's a bootstrapping problem :-) (Debian has solved those before of course, but with community sentiment like the above maybe noone is motivated to bother.)
Unless I am a windows administrator, my question is: Why should I?
There is literally ZERO reason for me as an administrator *nix machines to ever touch pwsh.
> but there's some genius in there
I am sure there is. But it's buried very well under layers upon layers of deep integration with windows and .NET, the attempt to shoehorn a character-based shell into working with objects somehow, and a syntax that rivals enterprise java in its verbosity.
> nd specifically the help system is categorically better
Is it? Why? Man pages, infopages, and `apropos` all exist. Individual man pages may be bad, but the system as a whole is solid. It also isn't dependent on the shell. All these mechanisms are just normal programs that can be executed by any shell.
> a rising tide lifts all ships but bash is the mooring block.
What?
You do know it runs on Windows, Mac (amd64/arm64) and Linux(amd64/arm)? There is definitely integration with .net, which is available for the same platforms. The integration with .net is part of its power for me.
Verbosity can increase readability.
> Is it? Why? Man pages, infopages, and `apropos` all exist. Individual man pages may be bad, but the system as a whole is solid. It also isn't dependent on the shell. All these mechanisms are just normal programs that can be executed by any shell.
You will not loose those tools and their man pages when using PowerShell. He is referring to the documentation of all helper functions defined within PowerShell. When you create a helper function in Bash, how do you document it and what tool can you use to consult that documentation?
Bash does not have named parameters for its functions, let alone metadata on them…
"Runs somewhere" and "Is useful there" are two very different things.
> Verbosity can increase readability.
And usually it hinders readability. If anyone disagrees, he may explain how enterprise Java is more readable than Python, Go or Rust code. And yes, I do consider Rust more readable than Enterprise Java.
And that's when we talk about PROGRAMMING LANGUAGES. We are, however, talking about SHELL LANGUAGES. Other than most PLs, shells are in fact written more than they are read, so yes, "typeability" and terseness is a feature in shells, not a problem. And before anyone says "autocomplete": If a shell requires autocomplete to be somewhat useable, I will look for another shell.
> You will not loose those tools and their man pages when using PowerShell.
Did I say I will? That line was in reply to the statement that "the help system is categorically better", a statement I happen to disagree with.
> He is referring to the documentation of all helper functions defined within PowerShell.
And I am refering to the documentation that is defined within the shell environment on *NIX terminals.
> When you create a helper function in Bash, how do you document it and what tool can you use to consult that documentation?
Off the top of my head:
- I can embed a `-h --help` flag directly in the script
- I can write a manpage and use it via `man NAME`
- A manpage is also discoverable by the `apropos` program
- If it's a builtin I can use bashs builtin `help PATTERN`
- I can write an entry for the `info` program
So yeah, I'd say there are more than enough methods, all of which are well established in the shell ecosystem, and work seamlessly with it.> Bash does not have named parameters for its functions, let alone metadata on them…
Which would truly be a bummer if bash needed named parameters. Since it doesn't, I don't see why this would be an advantage. If I want named params for a shell script, I can write it in python.
> Bash does not have named parameters for its functions, let alone metadata on them…
Come to think of it, actually a bash function can indeed have named parameters. Because that's exactly what command line flags with values are :-)
# these invocations are equivalent
awesome_util --source www.example.com --ignore-headers --dest file
awesome_util --dest file --source www.example.com --ignore-headers
awesome_util --ignore-headers --dest file --source www.example.com
In this example, it doesn't matter in what order I put the values for source, dest or the boolean to ignore headers, as they are all named by the associated command line flag.Compare for example the following helper code used for git command completion inside Bash and inside PowerShell.
Bash: https://github.com/git/git/blob/master/contrib/completion/gi... PowerShell: https://github.com/dahlbyk/posh-git/blob/master/src/GitPromp...
I believe this is clean Bash code and clean PowerShell code, and a script with a certain complexity. The functions inside the Bash script are documented using comments, the ones inside the PowerShell script are documented using "structured comments" (similar to javadoc/xmldoc/...). The parameters of the functions inside the PowerShell script also contain metadata which is used to provide completion on the commandline and similar functionality as the command line flags you demonstrated.
I just learned about 'getopts' in Bash, which you can actually also use to implement parameters to a Bash function. So what you are showing on a script level, can also be applied for functions. Did not know about that.
Still, not saying PowerShell is better than Bash in a Linux context, but it seems a lot of Linux users have a gut reaction to right out reject PowerShell. I think it does have some advantages for certain use cases, like more complex scripts, a cross-platform context, ... and of course, for someone with a .NET background it's easier to program more complex things with it.
You literally cannot write a powershell function that doesn't support get-help <myfunc>. So that's already a win it's self documenting because of the type system. The better the developer uses the type system the better the generated help. Sticking to the standard format for help (which is generated for you again from tab-complete) enhances this help document further. Finally, adding a url(https://learn.microsoft.com/en-us/powershell/scripting/devel...) lets the builtin update-help download new help, independent of publishing a new cmdlet version. So authors can fix typos/wording or add translations or examples without having to issue a release.
I've been doing linux sysadmin at least a decade, literally never heard of apropos before. I disagree that leaving this up to the authors is beneficial. When I'm lost and confused consistency is key.
Because this it builtin by default, it's worth it for the authors to add.
A lot of odd pwsh syntax is precisely because it's a proper language in a shell format, and just by that nature there's some ugly stuff in there. < > is already used so -le -gt -lte -eq exists.
Because it's a typed structured language, you will never have it without tab-complete, it's just designed in. That's the answer to maintain readability and typeabillity they chose. Bash just didn't choose readability. they both have alias' for common things. You may disagree but I would say that's just like refusing to use dot-sourcing or import statements in any language. It's there to use.
Your final remark about python I feel just adds to my point of don't bother with bash. I'd almost insist a shell that does even less then pwsh/bash and forced you to use a proper language sooner would be better.