PowerShell is MIT licensed, cross-platform Windows, Linux, macOS compatible, and you can download it in various installers and packages here: https://github.com/PowerShell/PowerShell/releases

for anyone who wants to try the newer version on Windows, get either Windows Terminal (from Microsoft Store or Github releases: https://learn.microsoft.com/en-us/windows/terminal/install) or Visual Studio Code. The classic Windows' command prompt console host engine just can't do Unicode and fonts and colours and Unix shell escape sequences.

After that, find something which will immediately trigger you to froth at the mouth, hurry onto some Microsoft forum and post about how Microsoft is the devil. Here's some popular choices, many of them valid complaints: ('curl' and 'wget' on Windows override the real programs with M$ imposters). (gci doesn't support the parameters of either dir or ls). (aliases work differently to Unix shells). (almost everything works differently to Bash). (gci -recurse is frustratingly slow). (it doesn't have a CLI text editor like nano). (you don't understand that GNU and Unix utilities aren't "Bash"). (PowerShell remoting with enter-pssession and invoke-command aren't SSH). (there isn't any sudo because Windows isn't Linux). (Execution policies are annoying). (it doesn't use UTF8 everywhere always). (backslash, the one true Unix escape character isn't PowerShell's escape character). (Line endings aren't Unix line endings). (having to use sigils to disambiguate between shell and code is worse than Python for coding and worse than Bash/cmd for shelling). (You want > to be both numeric comparison and/or Unix shell IO redirect and it's not). (you hate Verb-Noun and the one true way is Noun-Verb). (byte streams don't pipeline well or quickly). (It's verbose which you hate, but the elastic syntax one-liners are unreadable which you hate, it should have exactly the right amount of verbosity which coincidentally is exactly the amount you are comfortable with).

Moving on from there, avoid falling for the tempting usermode filesystem equivalent, which is abandoned and only exists for backwards compatibility making everything slower. Avoid falling for the declarative host config system Desired State Configuration (DSC) which is semi-abandoned and only hangs around for backwards compatibility. Control your enthusiasm about .NET/C# LINQ in a shell, because nope. Prepare yourself for the weirdness of a programming language which has shell style dynamic scoping instead of lexical scoping, shell style output handling where all output goes to the pipeline, pipeline obsessed array unrolling which spills the contents of containers all over the floor if you aren't paying attention, having to learn that there's more to output than just stdout and stderr and that the host and pipeline are different outputs, and that there's a lot of non-powershelly .NET and Windows stuff poking through everywhere. Prepare your armoured-toe boots for a large number of footguns and bugs in what is an intricate and complex shell/scripting language mashup.

Moving on from there, it's a REPL:

$x = 5
$x + 3

Numeric literals in hex and binary:

0xff
0b1010

Strings in single quotes are literal:

'foo $bar'

Strings in double quotes are not literal:

$bar = 'hello'
"foo $bar $( 4 + 3 )"

It's a shell:

ping google.com

It's introspective:

gcm ping # get-command details of ping
gcm p* # commands starting with pi
help gcm

Function calls don't use () or "return" because shell-style usage and behaviour, variable names and function calls aren't case sensitive:

PS C:\> function test($Left, $Right) { $left + $right }
PS C:\> test 4 6
10

PS C:\> test -Left 4 -Right 6 # named parameters
PS C:\> test -L<ctrl+space> # autocomplete

Reach for .NET libraries:

PS C:\> [System.Ma<ctrl+space> # autocomplete to explore and find System.Math
PS C:\> [System.Math]::<ctrl+space> # autocomplete to find e.g. [System.Math]::Pow(4, 5)

Basic data types:

$array = 1,2,3
$array | foreach { $_ }

$hash = @{KeyA = 4; KeyB = "b"}
$hash.keyC = 5
$hash['keyD'] = get-childitem

$x = 'KeyA'
$hash.$x # oooh

on Windows:

gci | ogv # out-gridview

Text filter ("grep ish"):

gc words.txt | sls '[iou]' # get-content and Select-String

Objects:

ls | select Las<tab> # tab complete will pickup the available properties
# on the objects coming through the pipeline, where possible

ls | select LastWriteTime, FullName # two properties, kept separate, no text parsing

ls | % {$_.LastAccessTime.DayOfWeek} # the access time is a .NET System.DateTime,
# not a timestamp or text string.

ipcsv data.csv | select col1, col3 # import-csv, select-object

$hash = @{KeyA = 1; KeyB = "foo"}
[pscustomobject] $hash # casting

(Objects are used as containers for multiple properties and keeping them separate; it's not a full "object oriented programming with inheritance and interfaces" kind of shell/language, although it has some nods to that).