Skip to content

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-Object and Measure-Object
  • Why ls works in PowerShell but ls -la fails

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:

$PSVersionTable.PSVersion
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      ...    ...

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 Process or GetProcess gives "is not recognized as the name of a cmdlet".
  • Tab completes cmdlets and parameters: type Get-Ch and press Tab, or -Des and 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
Get-Command -Noun Process
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:

Get-Date
Get-Date | Get-Member -MemberType Property

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:

"tramuntana".Length         # 10
"tramuntana".ToUpper()      # TRAMUNTANA

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?

Get-Process | Where-Object WorkingSet64 -gt 100MB | Measure-Object

PowerShell understands 100MB as 104,857,600 bytes. And services are objects too:

Get-Service | Where-Object Status -eq Running | Measure-Object

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:

Get-Alias ls
CommandType  Name                ...
-----------  ----                ...
Alias        ls -> Get-ChildItem

An alias is a nickname for a cmdlet. Typing ls really runs Get-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-Object and Measure-Object filter, order, pick and count. Comparisons are words like -gt; > still redirects.
  • ls is an alias of Get-ChildItem, so Linux options like -la fail.

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 ls program
  • 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
  • 100MB is not a number PowerShell can read
  • Where-Object always saves its result to a file
  • WorkingSet64 is 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.