# PowerShell Scripting Crash Course After having followed the [README.md](./README.md), `.ps1` scripts in the same folder as `$PROFILE.CurrentUserAllHosts` will be available in `$env:PATH` globally: ```powershell # Open the $PROFILE folder explorer (Split-Path -Parent $PROFILE.CurrentUserAllHosts) codium (Split-Path -Parent $PROFILE.CurrentUserAllHosts) # Or start directly editing a script notepad "$(Split-Path -Parent $PROFILE.CurrentUserAllHosts)\my-script.ps1" codium "$(Split-Path -Parent $PROFILE.CurrentUserAllHosts)\my-script.ps1" ``` # variables [PowerShell is as case-insensitive as possible.](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_case-sensitivity?view=powershell-7.3) This means `$MyInvocation` works just the same as `$mYinVoCAtiOn` among other things. Coming from a Unix background and preferring some consistency I like to pretend it is case-sensitive so in this repo I'll strive for that but it's worth keeping in mind. Especially since **the Microsoft docs use case a lot** in variable and cmdlet names. Variables use `$` to distinguish themselves and can be set with `=` ```powershell $a_variable = "this one is a string" $interpolate_a_string = "like this: $a_variable" ``` ## booleans There are a few constants to know: `$true`, `$false`, `$null`. Empty strings (`""`, `''`), `$null` and `0` evaluate as `$false` # if and while There are a handful of [comparison operators](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators?view=powershell-7.3) which can be used with `if` or `while` like this: ```powershell if ($val -eq "y") { Write-Host "value is a y" } else { Write-Host "value is not a y" } while ($num -lt 50) { $num = $num + 1 } ``` # param At the beginning of scripts and functions `param` list can be specified like this ```powershell param( [string]$name = "Anonymous", [int]$age, [switch]$silent ) ``` There are [a lot of different powers](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters?view=powershell-7.3) behind the square bracket syntax, [including custom validation](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters?view=powershell-7.3#validatescript-validation-attribute), but these are the basics. Use `[parameter(mandatory)]` to require one otherwise they are optional. The above param block could be used in a script like this: ```powershell if ($silent) { exit } Write-Host "Hello $name" if ($age) { Write-Host "according to the -age you provided you are: $age" } ``` And run like this: ```powershell name_and_age.ps1 -name "Rose" -age "27" # or, arguments are also positional! name_and_age.ps1 "Rose" "27" ``` # functions Functions use `param` too (instead of parenthesis like other languages). The last value is the `return` result, (which you can also use to `return` early... or just regularly if you want) ```powershell function My-Add { param( [parameter(mandatory)][int]$x, [parameter(mandatory)][int]$y, ) $x + $y } ``` # foreach Works on [arrays](https://learn.microsoft.com/en-us/powershell/scripting/lang-spec/chapter-09?view=powershell-7.3#92-array-creation), which can be concatenated with `+` and `+=` by the way. ```powershell $letterArray = "a","b","c","d" foreach ($letter in $letterArray) { Write-Host $letter } ``` # items and paths In PowerShell files and folders are called items. Some useful cmdlets for working with them are: - [`New-Item`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/new-item?view=powershell-7.3#description) - create a file or folder - [`Remove-Item`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/remove-item?view=powershell-7.3#description) - delete a file or folder - [Move, Invoke, Rename etc...](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/?view=powershell-7.3) Here's how to loop through files in a folder using [`Get-ChildItem`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-7.3#description): ```powershell foreach ($image Get-ChildItem .\images\* -Include *.png) { Write-Host $image.BaseName } ``` There are also a handful of useful functions for dealing with path strings by the names of [[Verb]-Path](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/?view=powershell-7.3). Here are some examples: ```powershell # Get parent folder Split-Path -Parent $path # Test if a file exists. For folder use `-PathType container` Test-Path -Path $path -PathType leaf ``` # See Also - [About scripts (learn.microsoft.com)](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts?view=powershell-7.3)