PowerShell
Step 3. The Pipe (|) — A Way of Thinking That Assembles Commands
Level 0 — Understanding How to Operate a Computer and How It’s Structured | Difficulty ★★☆☆☆ | Estimated time: 2–3 hours
Prerequisites: Step 2 complete. We’ll work in Windows PowerShell.
- What you need: a Windows PC, PowerShell.
- Safety: the lesson commands read process and file information. They do not stop processes or change files. Record inaccessible information and its error; do not elevate privileges just to reveal it.
- Caution: two pieces of syntax today (
{}and$_) will feel unfamiliar. Don’t try to fully understand them yet — type them verbatim and build a feel first. We’ll explain why later.
Today is one of the most conceptually important days. Individual commands are just tools; the pipe is the way you “assemble” those tools. Most security investigations are problems like “show me only the processes that have been running suspiciously long” or “pull only the failed logins out of tens of thousands of log lines” — all of them assemblies of “list → filter → sort → trim.” Once this assembly mindset becomes second nature, unfamiliar problems start falling apart along the same skeleton.
1. Learning Objectives
By the end of this unit, you can:
- Pass a command’s output into the next command’s input with the pipe (
|) - Assemble the three machines
Sort-Object,Select-Object -First N, andWhere-Object - Design combined commands of the form “the top N things that are ○○” on your own
- Investigate the properties (tags) of an unfamiliar command with
Get-Member
2. Background Knowledge — Today’s Tools and Concepts
This section’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | Windows PowerShell 5.1 / PowerShell 7 — the pipe (|) operator |
| This section’s commands | Sort-Object (sort), Select-Object -First N (trim), Where-Object (filter), Get-Member (inspect properties), Measure-Object (count) |
| Concepts you need | objects and properties, $_ and {} syntax, comparison operators like -eq/-gt |
Imagine a factory. Raw material travels along a conveyor belt, and each station’s machine takes the material, does its job, and passes it to the next machine.
raw material → [cut] → [polish] → [package] → finished product
PowerShell’s pipe (|) is exactly that conveyor belt. The left command’s output rides the belt and becomes the right command’s raw material.
2-1. The Secret of PowerShell’s Pipe — Objects Travel, Not Text
A Linux pipe carries a byte stream, which can contain text or binary data. A following program interprets text according to its expected format. Between the PowerShell cmdlets used here, the pipeline carries objects with properties.
PowerShell is different. What rides the belt isn’t text but objects — “things with tags attached.” For example, what Get-Process passes along is one process at a time, each carrying tags (properties) like these:
one process object ├── Name: "chrome" ├── CPU: 245.3 ├── WorkingSet64: 892345600 ├── Id: 4520 └── ...
So the command on the right doesn’t “guess by tearing text apart” — it picks things out precisely, by tag name. Sort-Object CPU means “sort by the tag called CPU,” and it’s accurate regardless of how things happen to look on screen. That’s what people mean by “PowerShell’s pipe is precise.”
2-2. Meet This section’s Machines (Commands)
| Command | Role | Factory analogy |
|---|---|---|
Sort-Object property |
Sort by a given property | the lining-up machine |
Select-Object -First N |
Keep only the first N | the cutting machine |
Where-Object {condition} |
Pass through only what matches | the inspection machine |
Get-Member |
Show the list of tags (properties) | opening the blueprint |
2-3. $_ and {} — Operating the Inspection Machine
Only Where-Object has unusual syntax:
Where-Object {$_.CPU -gt 100}
How to read it:
{}(curly braces): “the inspection condition is inside here”$_: a pronoun pointing to “this one item passing by right now” on the belt$_.CPU: “the CPU tag of the item passing by”-gt: “greater than”
Read as a whole: “for each item passing by, let through only those whose CPU is greater than 100.”
Comparison operators use words instead of math symbols:
| Symbol | Meaning |
|---|---|
-eq |
equals |
-ne |
not equal |
-gt |
greater than |
-lt |
less than |
At first this syntax looks like an alien language. That’s normal. For today, just memorize and use it as a block, and let understanding catch up through repetition — this is actually the shortcut to acquiring syntax.
3. Follow Along
Before you begin. PowerShell normally passes objects through its pipeline. Select properties before presentation formatting; use Format-Table or Format-List only at the display end of a pipeline.
3-1. Check the Material — Get-Process
Get-Process
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
238 15 5120 18420 0.23 4520 1 ApplicationFrameHost
2156 89 185412 245800 45.12 8812 1 chrome
...
This is the list of programs (processes) running on this computer right now. Let’s look at the columns:
ProcessName— the program’s nameCPU(s)— accumulated processor time in seconds, not current CPU utilization (%) or elapsed time since launch.WS(K)— working set (pages resident in physical memory), shown in KiB. PowerShell 7 may show WS(M) in MiB instead. TheWorkingSet64property itself is measured in bytes.Id— the process number (PID)
There’s a lot of it — it fills the screen. Let’s start processing this material.
3-2. First Pipe — Sorting
Get-Process | Sort-Object CPU -Descending
Same list, but this time ordered by highest cumulative CPU time first. How to read it:
|— “pass the left result to the right”Sort-Object CPU— “sort by the tag called CPU”-Descending— “descending (biggest first).” Omit it for ascending (smallest first)
Pause and feel what just happened: “the items made by the machine on the left rode the belt and became raw material for the machine on the right.” Sort-Object doesn’t need to know what Get-Process is — sorting whatever is on the belt is its job.
3-3. Extending the Belt — Just the First 10
It sorted, but printing everything is still long. Let’s attach one more machine to the belt:
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
614 26 31684 28228 11,861.81 24832 1 worker
1997 97 753512 309468 4,024.48 41684 1 ChatGPT
2453 64 521032 168260 3,970.92 35616 1 chrome
... (up to 10 processes if enough exist; headings are extra)
Select-Object -First 10— “pick only the first 10”
This selects up to 10 processes by accumulated CPU time. It does not reproduce Task Manager’s current CPU percentage ranking. The table illustrates the output format; names, counts, and values vary with the time of execution. A blank CPU value is not proof of zero usage: access restrictions or a process exiting can prevent a value from being read.
Predict first: what would
Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 5show? WorkingSet64 went in where CPU used to be. Predict, then run it.
(Answer: up to 5 processes with the largest working sets. Task Manager’s default memory column may use a different metric. We only swapped a tag name, yet we answered a completely different question — that’s the power of assembly.)
3-4. The Inspection Machine — Where-Object
This time it’s not sorting but filtering.
Get-Process | Where-Object {$_.CPU -gt 100}
Only processes that have used more than 100 seconds of CPU remain. (If there are none, you may get nothing — that’s a normal result meaning “no matches.” Lower the number to 50 or 10 and try again.)
This command grabs each process passing along the belt and asks: “Is your CPU over 100?” — pass if yes, discard if no.
Now let’s select by name:
Get-Process | Where-Object {$_.ProcessName -in "powershell", "pwsh"}
-in checks for a match among the following values. Windows PowerShell normally runs as powershell; PowerShell 7 runs as pwsh, so the filter includes both. Other hosts may use another name. To inspect the current session itself, run:
Get-Process -Id $PID | Select-Object ProcessName, Id, CPU, WorkingSet64
3-5. Curious About the Tags? — Get-Member
The command for when you wonder “what other tags are there besides CPU?”:
Get-Process | Get-Member -MemberType Properties
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
...
CPU ScriptProperty System.Object CPU {get=$this.TotalProcessorTime.TotalSeconds;}
Id Property int Id {get;}
ProcessName Property string ProcessName {get;}
WorkingSet64 Property long WorkingSet64 {get;}
...
-MemberType Properties includes Property, ScriptProperty, AliasProperty, and other property kinds. CPU, for example, is a ScriptProperty. Details in the Definition column may vary between versions. Look at this list, think “ah, that property exists too,” and get ideas for your next combination. When you wonder about an unfamiliar command’s properties, Get-Member — an investigation habit you’ll use hundreds of times.
3-6. The Same Idea Works on Files — Applied Combination
The pipe isn’t just for processes. Get-ChildItem (file listing) can ride the same belt:
Get-ChildItem $HOME -File | Sort-Object Length -Descending | Select-Object -First 5
Read it as: select ordinary files directly under the home folder, sort by Length in bytes, and keep up to five. -File excludes folders. This does not search subfolders or calculate the total size of directories; hidden files are excluded by default.
The pattern so far:
(get a list) | (process: sort/filter) | (trim)
Just swap the material and the conditions onto this skeleton.
4. Missions & Exercises
Mission — Assembly Designer
Assemble commands yourself that answer the following questions. The answers are in Section 5, but build and run yours first, then compare.
- “Show me only processes using more than 500MiB (=524288000 bytes, the value of PowerShell’s
500MB) of memory (WorkingSet64)” - “Show me how many processes named powershell or pwsh are running right now” (hint: attach
| Measure-Objectafter the filter to count them) - “Show me up to 3 most recently modified ordinary files directly in the Windows System32 folder” (hint: the modification-time tag is
LastWriteTime) - “Show me processes sorted alphabetically by name, first 10 only” (hint: do you need -Descending this time?)
Exercises
Exercise 1. Explain one way PowerShell’s pipe differs from the Linux pipe.
Exercise 2. In Where-Object {$_.Length -gt 1000000}, what does $_ refer to?
Exercise 3. Assemble a command for “find only the zero-byte files in my home folder.”
Exercise 4. You want to know the list of properties (tags) available in some command’s output. What do you attach after it?
Answers & completion criteria · expand/collapse
5. Model Answers & Completion Criteria
Mission Walkthrough
# 1
Get-Process | Where-Object {$_.WorkingSet64 -gt 524288000}
# 2
Get-Process | Where-Object {$_.ProcessName -in "powershell", "pwsh"} | Measure-Object
# 3
Get-ChildItem "$env:WINDIR\System32" -File | Sort-Object LastWriteTime -Descending | Select-Object -First 3
# 4
Get-Process | Sort-Object ProcessName | Select-Object -First 10
More important than how many you got right is reviewing, for the ones you missed, which machine you chose wrong.
Exercise Answers
Answer 1. A Linux pipe carries a byte stream containing text or binary data. The PowerShell cmdlet pipelines in this lesson carry objects, allowing selection by property name instead of display-column position. Pipelines involving external executables require separate consideration.
Answer 2. It’s a pronoun pointing to the one item passing by right now on the pipe (belt). $_.Length means “the Length property of that item passing by.”
Answer 3.
Get-ChildItem $HOME -File | Where-Object {$_.Length -eq 0}
Use -File so Length unambiguously refers to file size. This checks visible files directly under the home folder. No matching files means an empty result. The comparison operator is -eq.
Answer 4. Attach | Get-Member. Example: Get-ChildItem | Get-Member. Use Get-Member -MemberType Properties to include all property kinds, such as ScriptProperty and AliasProperty as well as Property.
Completion Checklist
- [ ] I can explain that the pipe
|“passes the left result as the right side’s material” - [ ] I know the cmdlet pipelines in this lesson pass objects with properties
- [ ] I can build the combination
Get-Process | Sort-Object ... | Select-Object -First N - [ ] I can use the
Where-Object {$_ ... }shell from memory - [ ] I’ve built the habit of reaching for
Get-Memberwhen curious about properties - [ ] I assembled the 4 mission problems myself
6. Common Pitfalls & Fixes
Wall 1. Where-Object lets nothing through (empty result)
Three candidate causes: ① the number in your condition is too big — lower the threshold. ② A typo in the property name — check exact spelling with Get-Process | Get-Member -MemberType Properties. ③ Comparing text as if it were a number (or vice versa). Also remember that an empty result may not be a malfunction but simply “no matches.”
Wall 2. I forgot the {} or the $_
The script-block form used here combines braces with $_. A simplified comparison form such as Where-Object CPU -gt 100 also exists; do not mix the two forms. This one command has a peculiar shape, so memorize it as a shell: Where-Object { $_.property comparison }. Only the inside changes.
Wall 3. I used = and got an error (or a weird result)
In PowerShell, = is “assignment” (putting something into a variable), not “equality comparison.” Comparisons are -eq, size comparisons are -gt/-lt. You’ll be tempted by math symbols, but this is PowerShell tradition.
Wall 4. Sorting seems to happen as text, not numbers
Rarely, when a property is stored as a string, sorting puts “10” before “9.” Get-Process’s CPU/WorkingSet64 are numbers so this problem doesn’t occur here, but remember this trap — you’ll meet it later when handling CSV files and the like.
Wall 5. I don’t know what to attach after the pipe
Memorize it like a formula: “get a list → process it → trim it.” And when unsure, type one stage at a time. Run just Get-Process, then add | Sort-Object ..., then | Select-Object .... Extending the belt while confirming each stage’s output with your eyes is the beginner’s correct form.
7. Summary
This section’s Assembly Parts
| Machine (command) | Role | Example |
|---|---|---|
Sort-Object property -Descending |
Sort (biggest first) | Sort-Object CPU -Descending |
Select-Object -First N |
Trim to the first N | Select-Object -First 10 |
Where-Object {$_.property condition} |
Conditional filter | Where-Object {$_.CPU -gt 100} |
Get-Member |
Inspect the property list | Get-Process | Get-Member -MemberType Properties |
Measure-Object |
Count | ... | Measure-Object |
Comparison Operators
-eq (equals) / -ne (not equal) / -gt (greater than) / -lt (less than)
All-Purpose Skeleton
(get a list) | (sort or filter) | (trim)
Instincts That Matter More Than Commands
“Translate the problem into a conveyor belt.” “Find suspicious processes” is really “get a list → filter by a condition → trim for readability.” And attaching one stage at a time and checking is the beginner’s assembly method.
One nice-to-know: besides -First N, Select-Object can also pick only the tags (columns) you want to see, like Select-Object ProcessName, CPU. Try Get-Process | Select-Object ProcessName, CPU -First 5 — a technique you’ll use when making reports.
Once every box is checked, Step 3 is complete.
Practice verification record
Historical record. The dated record below describes the earlier lesson version. The current instructions include subsequent editorial corrections; that record does not certify every revised example.
2026-09-10 · Executed process listing, cumulative CPU sorting, filters, Get-Member, file sorting, and missions on Windows 11 with Windows PowerShell 5.1.26100.9444 and PowerShell 7.6.5. Live process values change continuously, so rankings are not fixed answer keys. Separate sample objects and newly created test files were used to verify conditions, ordering, and exclusion of folders. No processes were stopped and no system files were modified.
References: Microsoft Get-Process · Get-Member and property types · Linux pipe
ONE STEP FURTHER
Finished this lesson?
Check the completion criteria, then mark your progress.