PowerShell first contact¶
Exercise powershell-first-contact-annex.pdf · PDF
On Wednesday, to get the department column out of staff.csv, you counted commas: cut -d, -f2. It worked. But what if somebody adds a column in the middle? Your pipeline silently cuts the wrong one. What if, instead of counting, you could just ask for the field by its name?
That is what the other big shell does. Most company computers run Windows, and Windows administrators do their work in PowerShell. As a developer you will meet it in build scripts, in Visual Studio's terminal, in Azure. It is not "Bash for Windows": it thinks differently. Today you find out how.
What you will learn
- Read and guess cmdlet names from the Verb-Noun pattern
- Find a command and its help without the internet:
Get-Command,Get-Help,Get-Member - Explain that the PowerShell pipeline carries objects with named properties, not lines of text
- Build a pipeline with
Where-Object,Sort-Object,Select-ObjectandMeasure-Object - Why
lsworks in PowerShell butls -lafails
Open the terminal¶
Start win11 first: it takes a while to boot. Then Start → type terminal → Enter. Windows 11 opens Windows PowerShell 5.1, which comes with the system. Nothing to install.
Check which version you have:
If you see 7.x, you opened PowerShell 7, the newer cross-platform version. Everything on this page works in both.
A shell born in Barcelona¶
For years, Windows administrators lived in windows and clicks. The old command prompt, CMD, dates from the 1980s and was never meant for serious administration.
In 2002, a Microsoft engineer, Jeffrey Snover, wrote an internal document, the Monad Manifesto. His point: Windows needed a real shell, and simply copying Unix would not work. Unix stores its configuration in text files, so text tools like grep and cut are enough. Windows manages almost everything through programming interfaces, not text files. A Windows shell had to pass around something richer than text.
Windows PowerShell 1.0 was announced on 14 November 2006, at a conference in Barcelona. In August 2016 it became open source, and today PowerShell 7 also runs on Linux and macOS.
Careful: PowerShell is not CMD with a blue window
CMD is the 1980s command prompt. PowerShell is a different, much newer shell (2006) with its own language. They just both live on Windows.
Verb-Noun: names you can guess¶
A cmdlet (say "command-let") is a PowerShell command. Every cmdlet is named Verb-Noun.
| Cmdlet | What it does |
|---|---|
Get-Process |
Lists the running programs |
Stop-Process |
Stops one |
Get-Service |
Lists the services |
New-Item |
Creates a file or folder |
Get-ChildItem |
Lists the contents of a folder |
If you know one, you can guess the others. How would you stop a service? Stop-Service. Create a local user? New-LocalUser (you will use it very soon). Case does not matter: get-process works too.
Two typing tips:
- The name is one word with a hyphen.
Get ProcessorGetProcessgives "is not recognized as the name of a cmdlet". - Tab completes cmdlets and parameters: type
Get-Chand press Tab, or-Desand Tab.
Three lifelines¶
You don't need the internet to find your way. Three cmdlets answer almost every question:
| Cmdlet | The question it answers | In Bash you used |
|---|---|---|
Get-Command |
Which commands exist? Get-Command -Noun Process |
man -k |
Get-Help |
How do I use this one? Get-Help Get-Process |
man, --help |
Get-Member |
What is this thing I got, and what does it know? Pipe any object into it | nothing like it |
CommandType Name ...
----------- ---- ...
Cmdlet Debug-Process ...
Cmdlet Get-Process ...
Cmdlet Start-Process ...
Cmdlet Stop-Process ...
Cmdlet Wait-Process ...
Get-Help Get-ChildItem shows the SYNTAX section, which is always there. If it says it shows "only partial help", that is normal: the full help is downloaded with Update-Help (as administrator, with internet). Get-Help Get-ChildItem -Online opens the web page instead.
The third lifeline, Get-Member, is the new one. To understand it, you need the big idea of today.
Everything is an object¶
The analogy we keep all page: Bash pipes carry sheets of text. To get a piece of a sheet, you measure it with a ruler: "column 2, after the second comma". PowerShell pipes carry forms with labelled fields. To get a piece of a form, you ask for the field by its name.
An object is a bundle of data with named fields. Each field is a property. An object can also have actions it knows how to do: its methods.
flowchart LR
subgraph BASH ["Bash: sheets of text"]
direction LR
B1["<b>ps</b><br>prints lines"] -->|"text"| B2["<b>cut / sort</b><br>which column?"]
end
subgraph PWSH ["PowerShell: forms with fields"]
direction LR
P1["<b>Get-Process</b><br>sends objects"] -->|"objects"| P2["<b>Sort-Object</b><br>which property?"]
end
Try it with a date:
The first line prints today's date. The second one asks the date object what fields it has: Day, DayOfWeek, DayOfYear, Hour, Month, Year... You can read one field with a dot:
(Get-Date).DayOfWeek # Friday (on 19/02/2027)
(Get-Date).AddDays(100) # the date 100 days from today
AddDays is a method: an action the date knows how to do. The parentheses around Get-Date matter. Without them, PowerShell looks for a cmdlet called Get-Date.AddDays and fails.
Even a piece of text is an object:
Careful: the table on the screen is not the data
When PowerShell prints a table, it is only drawing a few fields of each object. The object usually has many more properties. To see them all, pipe it to Get-Member.
A pipeline of objects¶
Four cmdlets do most of the work in a PowerShell pipeline:
| Cmdlet | What it does | Closest Bash tool |
|---|---|---|
Where-Object |
Keeps only the objects that pass a condition | grep |
Sort-Object |
Orders the objects by a property | sort |
Select-Object |
Keeps some objects (-First 3) or some properties |
head, cut |
Measure-Object |
Counts (and sums, averages...) | wc -l |
Read this pipeline aloud like a sentence:
Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 3 ProcessName, Id, WorkingSet64
Get the processes, sort them by memory in use, biggest first, keep the first three, show me three fields. No columns counted. WorkingSet64 is the memory the process is using, in bytes. On a fresh win11 you will usually see MsMpEng (the antivirus), explorer or msedge on top.
How many processes use more than 100 MB?
PowerShell understands 100MB as 104,857,600 bytes. And services are objects too:
Measure-Object prints a Count field: the number of running services, usually several dozen.
Careful: > does not compare
Where-Object WorkingSet64 > 100MB does not mean "greater than". In PowerShell, as in Bash, > is redirection: it creates a file called 100MB. Comparisons are words:
| Operator | Means |
|---|---|
-eq |
equal |
-ne |
not equal |
-gt / -lt |
greater than / less than |
-ge / -le |
greater or equal / less or equal |
ls is a nickname¶
Type ls in PowerShell. It works! So PowerShell is like Linux? Not at all:
An alias is a nickname for a cmdlet. Typing
lsreally runsGet-ChildItem.
| You type | What really runs |
|---|---|
ls, dir, gci |
Get-ChildItem |
cat |
Get-Content |
cd |
Set-Location |
The aliases exist so newcomers feel at home. But the options are PowerShell's, not Linux's. That is why ls -la fails: Get-ChildItem has no -l or -a. PowerShell is another language that happens to share a few familiar words.
Only on Windows
Aliases such as ls and cat exist in Windows PowerShell. In PowerShell 7 on Linux they are not defined, so ls runs the real Linux ls. And cmdlets like Get-Service or Get-Volume only exist on Windows.
Bash vs PowerShell: first impressions¶
| Bash | PowerShell | |
|---|---|---|
| Born | 1989, for Unix-like systems | 2006, for Windows |
| The pipe carries | Lines of text | Objects with properties |
| To get one field | Count columns: cut -d, -f2 |
Ask by name: Select-Object Name |
| Command names | Short: ls, ps, wc |
Long and guessable: Get-ChildItem |
| Finding help | man, --help, help |
Get-Command, Get-Help, Get-Member |
| Comparing numbers | -gt inside [ ] |
-gt |
Some things are easier (names you can guess, no column counting). Some are harder (long names, a lot of typing). Both are true. Next session you do the same jobs in both shells and decide for yourself.
Key takeaways¶
- PowerShell (2006, Jeffrey Snover) is Windows' modern shell; it is not CMD, and it is not a copy of Bash.
- Every cmdlet is named Verb-Noun, so you can guess names:
Get-Process,Stop-Process,Get-Service. - Three lifelines:
Get-Command(what exists),Get-Help(how to use it),Get-Member(what this object has). - The PowerShell pipeline carries objects with named properties and methods, not lines of text: you ask for a field by name.
Where-Object,Sort-Object,Select-ObjectandMeasure-Objectfilter, order, pick and count. Comparisons are words like-gt;>still redirects.lsis an alias ofGet-ChildItem, so Linux options like-lafail.
Quick check¶
1. Which name follows the pattern of PowerShell cmdlets?
-
Get-Process -
process --list -
ListProcesses -
ps_get
Every cmdlet is named Verb-Noun, joined by a hyphen: a standard verb (Get, Stop, New...) and the thing it acts on. That is what makes the names guessable.
2. What travels through a PowerShell pipeline?
- Objects with properties
- Lines of plain text
- Files on the disk
- Pictures of the output
PowerShell passes objects from one cmdlet to the next. Each one carries named properties, so the next cmdlet can ask for WorkingSet64 or Status by name instead of counting columns like Bash does.
3. You have an object and do not know which properties it has. You pipe it to...
-
Get-Member -
Get-Help -
Get-Command -
Get-Alias
Get-Member asks the object itself which properties and methods it has. Get-Help explains how to use a cmdlet, and Get-Command lists which cmdlets exist.
4. In Windows PowerShell, what is ls?
- An alias of
Get-ChildItem - The Linux
lsprogram - A file inside
C:\Windows - A command that gives an error
ls is an alias: a nickname that runs Get-ChildItem. The options are PowerShell's, which is why ls -la fails. You can check it with Get-Alias ls.
5. Which cmdlet keeps only the objects that pass a condition?
-
Where-Object -
Sort-Object -
Select-Object -
Measure-Object
Where-Object is the filter, like grep in Bash: Where-Object Status -eq Running keeps only running services. Sort-Object orders, Select-Object picks, Measure-Object counts.
6. A classmate runs Get-Process | Where-Object WorkingSet64 > 100MB and finds a new file called 100MB in the folder. What went wrong?
-
>is redirection; greater than is written-gt -
100MBis not a number PowerShell can read -
Where-Objectalways saves its result to a file -
WorkingSet64is not a property of a process
In PowerShell, as in Bash, > redirects output into a file. Comparisons are words: -gt (greater than), -lt, -eq. PowerShell does understand 100MB as 104,857,600 bytes.
7. You want the date exactly 100 days from today. Pick the line that works.
-
(Get-Date).AddDays(100) -
Get-Date.AddDays(100) -
Get-Date | AddDays 100 -
Get-Date -AddDays > 100
Get-Date returns a date object, and AddDays is one of its methods. The parentheses make PowerShell run Get-Date first, then call the method on the result. Without them it looks for a cmdlet with that whole name.
Two shells, two ways of thinking. Next session you put them face to face: Bash and PowerShell side by side.