PowerShell/CrashCourse.md

149 lines
5.2 KiB
Markdown
Raw Normal View History

2023-06-17 21:11:38 +00:00
# PowerShell Scripting Crash Course
2023-06-18 17:24:35 +00:00
After having followed the [README.md](./README.md), `.ps1` scripts in the same folder as `$PROFILE.CurrentUserAllHosts` will be available in `$env:PATH` globally:
2023-06-17 21:11:38 +00:00
```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"
```
2023-06-24 19:03:29 +00:00
# Get-Help
You can learn about pretty much anything in PowerShell with the `Get-Help` cmdlet.
```powershell
Update-Help
Get-Help Get-Help
Get-Help New-Item
Get-Help Get-ChildItem
```
2023-06-18 17:24:35 +00:00
# variables
2023-06-19 14:04:31 +00:00
[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.
2023-06-18 17:24:35 +00:00
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"
}
2023-06-24 19:03:29 +00:00
if (-not $some_switch) {
# a bang ! also works...
}
$num = 0
2023-06-18 17:24:35 +00:00
while ($num -lt 50) {
$num = $num + 1
}
```
2023-06-17 21:11:38 +00:00
# param
2023-06-18 17:24:35 +00:00
At the beginning of scripts and functions `param` list can be specified like this
2023-06-17 21:11:38 +00:00
2023-06-18 17:24:35 +00:00
```powershell
param(
[string]$name = "Anonymous",
[int]$age,
[switch]$silent
)
```
2023-06-17 21:11:38 +00:00
2023-06-19 03:55:08 +00:00
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:
2023-06-18 17:24:35 +00:00
```powershell
2023-06-22 15:37:38 +00:00
# Name-And-Age.ps1
2023-06-24 19:03:29 +00:00
if (-not $silent) {
Write-Host "Hello $name"
if ($age) {
Write-Host "according to the -age you provided you are: $age"
}
2023-06-18 17:24:35 +00:00
}
```
And run like this:
```powershell
2023-06-22 15:37:38 +00:00
Name-And-Age.ps1 -name "Rose" -age "27"
2023-06-18 17:36:28 +00:00
# or, arguments are also positional!
2023-06-22 15:37:38 +00:00
Name-And-Age.ps1 "Rose" "27"
```
2023-06-18 17:24:35 +00:00
# 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(
2023-06-19 03:55:08 +00:00
[parameter(mandatory)][int]$x,
[parameter(mandatory)][int]$y,
2023-06-18 17:24:35 +00:00
)
$x + $y
}
```
2023-06-19 03:55:08 +00:00
# foreach
2023-06-18 17:24:35 +00:00
2023-06-19 03:55:08 +00:00
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
2023-06-19 05:01:03 +00:00
foreach ($image Get-ChildItem .\images\* -Include *.png) {
2023-06-19 03:55:08 +00:00
Write-Host $image.BaseName
}
```
2023-06-22 15:37:38 +00:00
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). Note that in PowerShell folders are `container`s and files are `leaf`s. Here are some examples:
2023-06-19 03:55:08 +00:00
```powershell
# Get parent folder
Split-Path -Parent $path
# Test if a file exists. For folder use `-PathType container`
Test-Path -Path $path -PathType leaf
```
2023-06-17 21:11:38 +00:00
# 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)