Powershell Cheatsheet
Categories: Programming
Tags: Scripting Powershell
This article teaches the fundamentals of Powershell scripting. It can serve people as a refresher for those who don't touch Powershell too often. It assumes the reader has basic knowledge of Bash scripting.
As of writing, Powershell 7.5 is the latest version used in this article.
Introduction: Getting a Taste of PowerShell
Both Powershell and other scripting languages have common command aliases (e.g. ls, dir, cd, echo). However, one aspect that stands out is Powershell's slightly more verbose and descriptive syntax.
Powershell commands are called "cmdlets" (pronounced "command-lets"). They primarily use a verb-noun pair and are case-insensitive (get-help is the same as Get-Help).
Note:
- As specified in this manual, PowerShell uses the term verb to describe a word that implies an action even if that word isn't a standard verb in the English language. For example, the term "New" is a valid PowerShell verb name because it implies an action even though it isn't a verb in the English language.
- Both parameters and cmdlets are case-insensitive.
Alongisde cmdlet, Powershell comes bundled with cmd.exe (Command Prompt) commands. They are legacy DOS commands integrated into Powershell for backwards compatibility. Such commands include dir, ping, copy, and net.
Examples of cmdlets include:
Get-AliasGet-CommandGet-HelpSelect-StringStart-ProcessEnd-ProcessGet-DateClear-SessionGet-Process
Note: If you're on Ubuntu Linux, you can install and use the command pwsh as an experiment. Do note that some features are not consistent or are limited.
The first three most important important Powershell cmdlets to acquaint are Get-Help, Get-Alias and Get-Command.
Get-Help
Like man or info in Linux, Get-Help is your best friend. It will help you gather information about a specified command. Although Get-Help can accept cmd.exe commands, it is generally better to use /? instead.
Get-Help additionally offers three different options. When we type get-help get-help and read under the the REMARKS section, we will see this:
To see the examples, type: "get-help Get-Help -examples".
For more information, type: "get-help Get-Help -detailed".
For technical information, type: "get-help Get-Help -full".
Furthermore, you can use help or man which displays one screen of text at a time. Do note however that the navigation is limited and you cannot scroll one line up like like in less.
<cmdlet-name> -? is also an option (-? is dentical to Get-Help), but it only works for cmdlets.
Get-Alias
For Get-Alias, both dir and ls actually run Get-ChildItem. We can check by typing Get-Alias ls or Get-Alias dir:
They give:
PS C:\Users\garen> get-alias dir
CommandType Name Version Source
----------- ---- ------- ------
Alias dir -> Get-ChildItem
PS C:\Users\garen> get-alias ls
CommandType Name Version Source
----------- ---- ------- ------
Alias ls -> Get-ChildItem
If Powershell reports that the leading alias does not exist, we can verify all the aliases like so:
PS C:\Users\garen> get-alias
CommandType Name Version Source
----------- ---- ------- ------
Alias % -> ForEach-Object
Alias ? -> Where-Object
Alias ac -> Add-Content
Alias asnp -> Add-PSSnapin
Alias cat -> Get-Content
Alias cd -> Set-Location
Alias CFS -> ConvertFrom-String 3.1.0.0 Microsoft.PowerShell.Utility
Ideally, grep will come in handy for this situation. But since we're using Powershell, the alternative is Select-String (its alias is sls).
PS C:\Users\garen> get-alias | sls ls
cls
ls
sls
Well that's disappointing (insert "mom, can we have" meme).
To remedy this, we'll need Out-String with the passing -Stream argument.
If you didn't understand, it's not something to worry too much for now, but it's here to stay for grep lovers like me:
PS C:\Users\garen> get-alias | out-string -stream | sls ls
Alias cls -> Clear-Host
Alias gcs -> Get-PSCallStack
Alias ls -> Get-ChildItem
Alias sls -> Select-String
Get-Command
Typing Get-Command without arguments will provide you a list of cmdlets, aliases, and functions available in your current session.
If you include the asterisk, it will show everything including the executable applications (e.g. notepad.exe, 7z.exe, python.exe) set in the PATH environment variable ($Env:PATH).
I/O in PowerShell
Output Streams in Powershell
An important clarification needs to be said about Powershell ouput streams...
Both Powershell and Bash share stdin, stdout and stderr streams. However, unlike Bash, Powershell handles the output stream differently because it doesn't process texts like its Bash counterpart. Instead, it processes and outputs .NET objects.
This is because Powershell is an object-oriented scripting language. Everything is an object in Powershell. In fact, when you call any cmdlet, it will always return one or more .NET objects. You can verify cmdlets returning an object by typing Get-Member after a pipe opreator |:
Note: Recall... Pipeline: A sequence of one or more commands separated by a
|.
get-alias | get-member
TypeName: System.Management.Automation.AliasInfo
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
...
emotingCapability Property System.Management.Automation.RemotingCapability RemotingCapability {get;}
Version Property version Version {get;}
...
Powershell has six output streams and each has its dedicated write cmdlet. Both "Success Stream" and "Error Stream" are mapped to *nix's stdout and stderr respectively.
| Stream # | Description | Write Cmdlet |
|---|---|---|
| 1 | Success Stream | Write-Output (alias: echo) |
| 2 | Error Stream | Write-Error |
| 3 | Warning Stream | Write-Warning |
| 4 | Verbose Stream | Write-Verbose |
| 5 | Debug Stream | Write-Debug |
| 6 | Information Stream | Write-Information, Write-Host |
| n/a | Progress Stream | Write-Progress |
| * | All Streams | n/a |
Redirecting Outputs in Powershell
Both Bash and Powershell share the same feature for redirecting output (> for overwrite, >> for append). Still, there are two other ways:
Out-File
Like >, it sends output to a file. If there are no parameters, it is no different to using >. There are several ways to use it.
The parameter -FilePath is kind of like -o in *nix-based systems. Although it is optional, it is better to include it in your scripts for legibility purposes. For example:
get-process | out-file -filepath .\Process.txt
Will create a txt file with all running processes information. We can also pass the argument -Encoding ascii to ensure in our scripts that the file is written using ASCII encoding:
get-process | out-file -encoding ascii -filepath .\Process.txt
By default, each line will hold 80 characters when writing. If you expect an output with a line exceeding that limit, it will truncate unless you specify using the -Width parameter:
get-process | out-file -encoding ascii -filepath .\Process.txt -Width 100
Now that you have an existing file, you might not want to overwrite it. With -NoClubber, it will prompt the user that the file cannot be overwritten.
PS C:\Users\garen\Documents\Surplus> get-process | out-file -filepath process.txt -encoding ascii -noclobber
out-file : The file 'C:\Users\garen\Documents\Surplus\process.txt' already exists.
At line:1 char:15
+ ... t-process | out-file -filepath process.txt -encoding ascii -noclobber ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceExists: (C:\Users\garen\...lus\process.txt:String) [Out-File], IOException
+ FullyQualifiedErrorId : NoClobber,Microsoft.PowerShell.Commands.OutFileCommand
To append an existing file, we type -Append:
PS C:\Users\garen\Documents\Surplus> echo "last line" | out-file -filepath .\Process.txt -append
PS C:\Users\garen\Documents\Surplus> tail .\Process.txt
175 12 1788 4384 1200 0 wininit
278 12 2388 16092 17244 15 winlogon
217 11 2440 12936 26248 14 winlogon
239 13 3224 5672 7016 0 wlanext
512 24 6596 14300 5092 0 wslservice
424 20 15812 39024 22132 0 WUDFHost
last line
Tee-Object
The Tee-Object cmdlet is very similar to Out-File. The only difference is that it will send the output of a command in two directions (like the letter "T"). It stores the output to a file or variable AND sends it down the pipeline:
PS C:\Users\garen\Documents\Surplus> echo "content of hello.txt" | tee-object -filepath .\hello.txt
content of hello.txt
Both Tee-Object and Out-File share -FilePath, -Encoding, and -Append parameters.