Pipeline and chain operators (|| and &&) now in pwsh
github.com
github.com
Also worth taking a look at the RFC[0] and the original issue[1].
Just to address some questions in the comments:
These operators had no equivalent in PowerShell previously, but they’d always been planned from the outset. If you look at the diffs in the parser, one of the things taken out is a comment where we parse `&&`/`||` saying something like “we should implement this for v3” (I can’t seem to get a link on my phone but don’t have a computer handy). In [1], mklement0 gives an excellent history of the request for these operators. I owe a blog post on this, so hopefully I can expand upon that.
Also, the pwsh/PowerShell thing exists partially because of needing to exist side-by-side with Windows PowerShell and partially because it wasn’t always clear that PowerShell 7 would be the direction of PowerShell into the future.
As a result, pwsh refers to PowerShell 6/7. PowerShell 6 was called PowerShell Core, but since PowerShell 7 has restored compatibility with a lot of Windows functionality, we’ve dropped the Core for PowerShell 7. And since PowerShell 5.1 and below are bound to Windows, they’re now qualified as Windows PowerShell.
Finally, a lot of users call PowerShell `posh`, but that was already the name of a shell in the Linux ecosystem, and after an early lesson with clobbering native utilities with aliases on *nix, the PowerShell team wanted to be good citizens.
Feel free to fire any questions at me too!
[0]: https://github.com/PowerShell/PowerShell-RFC/pull/192 [1]: https://github.com/PowerShell/PowerShell/issues/3241
Did you ever talk to the owner of `posh`? https://www.commandlinux.com/man-page/man1/posh.1.html Or think about using the `alternatives` system (which handles 'sendmail' 'node' and other shared names)?
I wasn’t on the team when that change was made but I think it was discussed in [0].
I’m not certain, but I suspect the reasoning went that a new name was needed to not clash with `powershell.exe` but it wasn’t certain to be `posh`. So unlike `node`, which had a clashing name from the outset, PowerShell never used or owned `posh`, making the choice of `pwsh` a simpler way to avoid clobbering another tool (and the subsequent complexity of the processes you mentioned).
There's definitely a learning curve (and it's harder to find information online), but once you get used to it, it's actually a pretty pleasant, cross-platform scripting experience. I'd definitely say that I'm comfortable doing more advanced scripts in powershell than I ever was in bash. If I had to use anything more complex than a for-loop in bash, I would reach for a "proper" programming language - but I can do quite a bit more in powershell without having to switch.
In contrast, bash scripting is basically entirely lowercase with very minor exceptions.
/r/PowerShell is really helpful if you are stuck also there is a Slack POSH group that is really helpful.
Get-Alias to see them all. "get-alias -Definition Select-String" to look for one for a specific command.
get-content -> cat
set-location -> cd
get-childitem -> ls
etc
But powershell just looks so damned ugly to me! It's too verbose, and the idiomatic Pascal-Kebab-Case thing is just weird.
I know powershell has aliases for common things, like `ls` or `wget`, but your scripts are no longer cross-platform if you use them, as you'll use the powershell functions on Windows, but the Linux commands on Linux.
I've tried so hard to like it for so long, but I just... can't.
For TAB-completion I use MenuComplete instead of the default (Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete) as it gives you IPython-like completion menus. With something like posh-git, it's amazing: you can type git checkout and then press TAB and have an interactive menu of the branches you can switch to; or if you've done a 'git status' you can then do git add, press TAB and you get a menu that intelligently shows you what files you might want to add.
My problem with powershell is it's verb-noun, I want to tab complete on Network, not get-Network
do you notice such an issue too?
pwsh is typically used to refer to Powershell Core for generally confusing reasons (mostly that on Windows "classic" Powershell continues to exist and be supported for various Windows-only tasks).
The older one is “Windows Powershell” to disambiguate them.
Powershell 7 (which just dropped RC2) is the Powershell going forward, it's based on .NET Core, its xplat, it's the one with all the dev resources assigned to it
Windows Powershell ships with windows, and is still at 5.1 at last check
Powershell Core 6 will be the only major version of Powershell core, 7 drops the core moniker
Chaining means you run one command followed by the other, so "&&" could be read as "and then"
Edit: nvm, I see below these are emulating the behaviour expected from bash. I guess it's called the pipeline operator because it uses the pipe symbol rather than doing any piping.
The POSIX shell spec calls them AND-OR lists, which I didn’t think was as descriptive.
To explain the pipeline idea a bit better, there are two ways of seeing a pipeline (in PowerShell or in a POSIX shell). One is at runtime; a command executes, taking its input from an input and spitting it out to an output. Chain a few commands together hooking the output of one to the input of another and you have a pipeline. (In POSIX shells of course these in/out locations are file descriptors, whereas in PowerShell they’re memory locations.)
But also a pipeline can refer to the syntax of a pipeline; something like `ls | grep “* .txt”` is a pipeline in terms of the POSIX shell grammar. Similarly in PowerShell, `gci | ? Name -like “* .txt”` is a pipeline syntax. And since you can chain these pipelines together with && and ||, I called the operators “pipeline chain operators”.
BTW, if you ever want to look at the abstract syntax tree of a PowerShell command, it’s very easy to do by wrapping it in a scriptblock and grabbing its AST:
$ast = { gi file.txt && rm file.txt }.Ast
$ast.EndBlock.Statements[0]cmd1; if ($?) { cmd2 } = cmd1 && cmd2
cmd1; if (-not $?) { cmd2 } = cmd1 || cmd2
Just your usual Powershell verboseness.