Practical PowerShell Command Recipes — Growing the Small Tools You Use Every Day
· Go Komura · PowerShell, Windows, Command Line, Automation, Business Efficiency, Legacy Asset Reuse
1. What to Grasp First
Once you have learned the basics of PowerShell, the next step is to grow your set of “small, frequently used tools” — that is what makes it practical in real work.
By small tools, we do not mean short aliases. In this article, instead of abbreviations like ls and cat, we use the full command names such as Get-ChildItem, Get-Content, and Select-String.
On that basis, we will make the following kinds of work doable in one line or a few lines:
Count items
Check total size
Remove duplicates
Aggregate by category
Extract only the values you need
Compare two sets of results
See the lines around a log hit
Send results to the clipboard
Save the output while also showing it on screen
Check environment variables and the network
PowerShell is useful even without writing long scripts. Start by growing your set of “frequently used building blocks” so you can gradually combine them in everyday work.
Rather than memorizing commands, what matters is being able to recall “in this situation, that building block applies.”
The code in this article is published on GitHub as a runnable sample set organized theme by theme following the chapter structure (recipe scripts and Pester tests).
powershell-practical-command-recipes - komurasoft-blog-samples (GitHub)
2. The Approach This Time
The premises are these three:
- Write commands with their full names
- Center the work on read-only commands
- Always pair change commands with target verification and
-WhatIf
For example, rather than learning the file deletion command straight away, it is safer to first internalize this flow:
Look at the targets
-> filter by condition
-> count them
-> save to CSV if needed
-> confirm the planned changes
-> execute
This article focuses on investigation, aggregation, comparison, and output rather than strong operations like deletion and stopping.
3. A Map of the Frequently Used Commands
The main commands we will use this time.
| What you want to do | Command |
|---|---|
| Check counts and totals | Measure-Object |
| Clean up duplicates | Sort-Object -Unique |
| Aggregate by category | Group-Object |
| Output only the columns you need | Select-Object |
| Process each element | ForEach-Object |
| Search strings | Select-String |
| Compare two sets of results | Compare-Object |
| Compute hash values | Get-FileHash |
| Use the clipboard | Set-Clipboard / Get-Clipboard |
| Output to both screen and file | Tee-Object |
| Measure processing time | Measure-Command |
| See error details | Get-Error |
| Check network reachability | Test-Connection / Test-NetConnection |
There is no need to learn all of them at once. We recommend learning them paired with a goal: “to count, Measure-Object,” “to group, Group-Object,” “to compare, Compare-Object.”
4. Counting — Measure-Object
The first frequent operation is counting.
Count the files in the current folder.
Get-ChildItem . -File | Measure-Object
To include subfolders:
Get-ChildItem . -File -Recurse | Measure-Object
The Count in the Measure-Object result is the number of items.
To see the total file size, aggregate Length.
Get-ChildItem . -File -Recurse |
Measure-Object -Property Length -Sum
As is, however, this is in bytes and a bit hard for humans to read, so convert it to GB.
$size = Get-ChildItem . -File -Recurse |
Measure-Object -Property Length -Sum
[math]::Round($size.Sum / 1GB, 2)
This is handy when you want a rough view of the total size of a folder.
5. Checking Maximum and Average Too
Measure-Object can produce not just sums but also maximums and averages.
Get-ChildItem . -File |
Measure-Object -Property Length -Sum -Average -Maximum -Minimum
This is useful for seeing the spread of file sizes.
You can also sum the cumulative CPU time of processes. The CPU from Get-Process is not a utilization percentage but the number of seconds of CPU time used since the process started.
Get-Process |
Measure-Object -Property CPU -Sum
Note, however, that this value is cumulative rather than an instantaneous CPU utilization, so it varies with the timing of the run and how long the processes have been up.
It is sufficient for investigative purposes, but for rigorous monitoring you also need dedicated monitoring tools and log design.
6. Extracting Just the Values — Select-Object -ExpandProperty
Select-Object is commonly used to choose columns.
Get-Process |
Select-Object Name, Id, CPU
This outputs “objects with the columns Name, Id, and CPU.”
When you want just the values, on the other hand, use -ExpandProperty.
Get-Process -Name notepad -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty Id
The same applies when extracting just file names.
Get-ChildItem . -File |
Select-Object -ExpandProperty Name
When you want to pass a command’s results to another command or a text file, -ExpandProperty is convenient.
For example, save just the list of file names.
Get-ChildItem . -File |
Select-Object -ExpandProperty Name |
Set-Content .\file-names.txt -Encoding UTF8
Select-Object Name and Select-Object -ExpandProperty Name look similar, but the shape of the result differs.
Select-Object Name
-> a table with a Name column
Select-Object -ExpandProperty Name
-> the Name values themselves
If you want CSV output, keeping it as a column is better; if you want to feed it into further string processing, the bare values are easier to handle.
7. Removing Duplicates — Sort-Object -Unique
Say you want a list of just the file extensions.
Get-ChildItem . -File |
Select-Object -ExpandProperty Extension |
Sort-Object -Unique
Running this shows only the deduplicated extensions, such as .txt, .log, and .csv.
You can also see just the distinct process names.
Get-Process |
Select-Object -ExpandProperty ProcessName |
Sort-Object -Unique
An example of extracting just the list of department names from a user list CSV:
Import-Csv .\users.csv |
Select-Object -ExpandProperty Department |
Sort-Object -Unique
When “the list is cluttered with lots of identical values,” remembering Sort-Object -Unique first is handy.
8. Aggregating by Category — Group-Object
When you want not just deduplication but “how many of each,” use Group-Object.
Count files per extension.
Get-ChildItem . -File |
Group-Object -Property Extension -NoElement |
Sort-Object -Property Count -Descending
Adding -NoElement omits the contents of each group, making the counts easier to read.
Count by service status.
Get-Service |
Group-Object -Property Status -NoElement
Count by event log level.
Get-WinEvent -LogName System -MaxEvents 500 |
Group-Object -Property LevelDisplayName -NoElement
Group-Object is well suited to grasping the big picture at the start of an investigation.
Which extensions are most common
Which service statuses are most common
Which error levels are most common
Which department has the most data
Use it when you want to see the distribution before drilling into details.
9. Creating the Columns You Need — Adding Computed Columns
File size is available via Length, but the unit is bytes. Looking at byte counts every time is painful, so it is convenient to create columns converted to MB or KB.
Get-ChildItem . -File |
Select-Object Name, @{Name="SizeKB"; Expression={ [math]::Round($_.Length / 1KB, 1) }}, LastWriteTime
An example that includes subfolders and lists the largest files first:
Get-ChildItem . -File -Recurse |
Sort-Object -Property Length -Descending |
Select-Object -First 20 FullName, @{Name="SizeMB"; Expression={ [math]::Round($_.Length / 1MB, 2) }}, LastWriteTime
@{Name="..."; Expression={ ... }} is the syntax for creating a computed column. It looks a little long at first, but it is used constantly in real work.
For example, you can display process memory usage in MB.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}
For reports, a column like SizeMB is far more readable than the raw Length.
10. Viewing Newest, Oldest, and Largest First
In PowerShell, sorting is done with Sort-Object.
See the most recently modified files.
Get-ChildItem . -File |
Sort-Object -Property LastWriteTime -Descending |
Select-Object -First 10 Name, LastWriteTime
See the oldest files.
Get-ChildItem . -File |
Sort-Object -Property LastWriteTime |
Select-Object -First 10 Name, LastWriteTime
See the largest files.
Get-ChildItem . -File -Recurse |
Sort-Object -Property Length -Descending |
Select-Object -First 10 FullName, Length
These three come up all the time.
Newest first -> LastWriteTime -Descending
Oldest first -> LastWriteTime
Largest first -> Length -Descending
They are frequent companions in log investigation, cleaning out unneeded files, and disk space investigation.
11. Use the Format Commands Only at the End, for Display
To make things easier to read on screen, use Format-Table and Format-List.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, WorkingSet |
Format-Table -AutoSize
For viewing the details of a single item, Format-List is handy.
Get-Process -Id $PID |
Format-List *
But Format-Table and Format-List are “for display.”
It is safer not to use them before outputting to CSV or before processing with subsequent commands.
# Avoid
Get-Process |
Format-Table Name, Id |
Export-Csv .\process.csv -NoTypeInformation
For CSV output, choose the columns with Select-Object.
# Correct
Get-Process |
Select-Object Name, Id |
Export-Csv .\process.csv -NoTypeInformation -Encoding UTF8
When in doubt, think of it like this:
Only viewing on screen -> Format-Table / Format-List
Using it later -> Select-Object
12. Making Log Searches a Bit More Convenient — Select-String
For string searching, use Select-String.
Select-String -Path .\logs\*.log -Pattern "ERROR"
Multiple patterns can be specified.
Select-String -Path .\logs\*.log -Pattern "ERROR", "WARN", "FATAL"
To see the surrounding lines, use -Context.
Select-String -Path .\logs\*.log -Pattern "ERROR" -Context 2
This also displays the two lines before and after each matching line, which is helpful when you want to see the context around an error.
To search for a literal string, use -SimpleMatch.
Select-String -Path .\logs\*.log -Pattern "[ERROR]" -SimpleMatch
The -Pattern of Select-String is normally treated as a regular expression. When you want to search for symbols like [ or . literally, adding -SimpleMatch keeps things clear.
For case-sensitive searching:
Select-String -Path .\logs\*.log -Pattern "Error" -CaseSensitive
Search results can also be kept in a CSV.
Select-String -Path .\logs\*.log -Pattern "ERROR" |
Select-Object Path, LineNumber, Line |
Export-Csv .\error-lines.csv -NoTypeInformation -Encoding UTF8
13. Replacing Strings
To replace part of a string, use -replace.
"server01.example.com" -replace "\.example\.com$", ""
When replacing the contents of a file, it is safer not to overwrite the original right away. Output to a separate file first.
(Get-Content .\appsettings.json -Raw) -replace "localhost", "db01" |
Set-Content .\appsettings.preview.json -Encoding UTF8
Review it, and apply it to the original file only if needed.
With configuration files and bulk replacements, too many matches lead to accidents. It is safer to check the targets with Select-String first and then replace.
Select-String -Path .\appsettings.json -Pattern "localhost" -SimpleMatch
14. Comparing Two Sets of Results — Compare-Object
Compare-Object is the command for seeing the differences between two lists.
For example, compare file name listings before and after a change.
Compare-Object `
-ReferenceObject (Get-Content .\before.txt) `
-DifferenceObject (Get-Content .\after.txt)
The meanings of SideIndicator are as follows.
| Shown | Meaning |
|---|---|
<= |
Exists only on the left side, i.e., in ReferenceObject |
=> |
Exists only on the right side, i.e., in DifferenceObject |
== |
Exists in both. Shown when -IncludeEqual is specified |
An example of saving and comparing the file name listings of folders:
Get-ChildItem .\before -File |
Select-Object -ExpandProperty Name |
Set-Content .\before-list.txt -Encoding UTF8
Get-ChildItem .\after -File |
Select-Object -ExpandProperty Name |
Set-Content .\after-list.txt -Encoding UTF8
Compare-Object `
-ReferenceObject (Get-Content .\before-list.txt) `
-DifferenceObject (Get-Content .\after-list.txt)
You can also look at changes in the service list.
Get-Service |
Select-Object Name, Status |
Export-Csv .\services-before.csv -NoTypeInformation -Encoding UTF8
After the change, export again.
Get-Service |
Select-Object Name, Status |
Export-Csv .\services-after.csv -NoTypeInformation -Encoding UTF8
Compare.
Compare-Object `
-ReferenceObject (Import-Csv .\services-before.csv) `
-DifferenceObject (Import-Csv .\services-after.csv) `
-Property Name, Status
Keeping before/after diffs of your work makes investigation and reporting easier.
15. Checking File Hashes — Get-FileHash
When you want to confirm that a downloaded file or a distributed file is identical, use hash values.
Get-FileHash .\installer.exe -Algorithm SHA256
To check all files in a folder at once:
Get-ChildItem .\downloads -File |
ForEach-Object { Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256 }
These can also be kept in a CSV.
Get-ChildItem .\downloads -File |
ForEach-Object { Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256 } |
Select-Object Path, Hash |
Export-Csv .\hashes.csv -NoTypeInformation -Encoding UTF8
Files that look identical by name alone can differ in content. For distributed artifacts, backups, and migrations, keeping hash values makes verification much easier.
16. Sending to the Clipboard — Set-Clipboard
When you want to paste command results into email or chat, sending them to the clipboard is convenient.
Get-Service |
Select-Object Name, Status |
ConvertTo-Csv -NoTypeInformation |
Set-Clipboard
To view the contents of the clipboard:
Get-Clipboard
To make it tab-delimited for pasting into Excel, set the delimiter of ConvertTo-Csv to a tab.
Get-Process |
Select-Object Name, Id, CPU |
ConvertTo-Csv -NoTypeInformation -Delimiter "`t" |
Set-Clipboard
If you just want to share results temporarily, this is easier than creating a file each time. But if you want to keep it as an audit trail, save it to a file with Export-Csv.
17. Showing on Screen While Saving to a File — Tee-Object
When you want to view results on screen while also saving them to a file, use Tee-Object.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, WorkingSet |
Tee-Object -FilePath .\top-process.txt
Tee-Object sends the pipeline results in two directions.
Show on screen
Save to a file as well
It suits “watch while recording” during an investigation. If you want to open the data in Excel later, however, Export-Csv is easier to work with.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, WorkingSet |
Export-Csv .\top-process.csv -NoTypeInformation -Encoding UTF8
Think of it as Tee-Object for the screen and Export-Csv for keeping tabular data, and it stays clear.
18. Keeping a Work Log — Start-Transcript
To record a sequence of operations, use Start-Transcript.
Start-Transcript -Path .\work-log.txt
The commands you run after this, and the screen output, are recorded.
End it.
Stop-Transcript
In investigative work, you will later want to check things like:
Which commands were run
Which folder the work happened in
What the results were
Whether errors occurred
Using Start-Transcript acts as insurance for the times you forget to take working notes. Be careful, however, when the work puts information on screen that must not be recorded, such as passwords or tokens.
19. Reading a CSV and Viewing by Condition
CSV comes up constantly in business data.
For example, suppose you have the following users.csv.
Name,Department,Enabled
Suzuki,Sales,true
Tanaka,Accounting,false
Sato,Sales,true
Read it.
Import-Csv .\users.csv
See only the people whose department is Sales.
Import-Csv .\users.csv |
Where-Object { $_.Department -eq "Sales" }
Output only the enabled users to a separate CSV.
Import-Csv .\users.csv |
Where-Object { $_.Enabled -eq "true" } |
Export-Csv .\enabled-users.csv -NoTypeInformation -Encoding UTF8
CSV values are usually treated as strings, so when comparing true / false or numbers, consider type conversion as needed.
For example, to see only rows with a score of 80 or higher:
Import-Csv .\scores.csv |
Where-Object { [int]$_.Score -ge 80 }
20. Viewing JSON Configuration Values
JSON is commonly used in configuration files and Web APIs.
$config = Get-Content .\settings.json -Raw | ConvertFrom-Json
$config
You can also look at just a specific value.
$config.Database.Host
An example of changing a value and saving to a separate file:
$config.Database.Host = "db01"
$config |
ConvertTo-Json -Depth 10 |
Set-Content .\settings.updated.json -Encoding UTF8
When working with JSON, Get-Content -Raw is the common choice. With -Raw, the whole file is read as a single string, which is clearer when handling multi-line JSON.
21. Viewing Environment Variables
Environment variables come up often for application settings and path checks.
View the list.
Get-ChildItem Env:
View the current user name.
$env:USERNAME
View the temp folder.
$env:TEMP
Split PATH for readability.
$env:PATH -split ";"
Set an environment variable for the current PowerShell session only.
$env:APP_MODE = "Development"
This setting is effective only inside the PowerShell session currently open.
To persist it as a user environment variable, do this:
[Environment]::SetEnvironmentVariable("APP_MODE", "Development", "User")
This is an operation that changes the environment, so on corporate PCs and production servers, confirm the scope of impact before doing it.
22. Checking Your Profile
PowerShell has a profile that is loaded at startup.
Check its location.
$PROFILE
Check whether it exists.
Test-Path $PROFILE
To create it:
New-Item -ItemType File -Path $PROFILE -Force
Open it in Notepad.
notepad $PROFILE
Putting frequently used settings and functions in your profile is convenient. However, writing too much complex processing there slows PowerShell startup and makes things hard to reproduce in other environments, so at first we recommend limiting it to frequently used paths and display settings.
23. Viewing Processes
In process investigation, the first move is usually to look at the largest memory consumers.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}
Filter by a specific name.
Get-Process -Name notepad -ErrorAction SilentlyContinue
When stopping a process, do not run it straight away — confirm with -WhatIf.
Stop-Process -Name notepad -WhatIf
If everything looks right, execute.
Stop-Process -Name notepad
In production environments, stopping a process can affect business operations. Before stopping, confirm the target, the users, and the recovery method.
24. Viewing Services
View the service list.
Get-Service
To see only stopped services:
Get-Service |
Where-Object { $_.Status -eq "Stopped" }
Find services that are set to automatic start but are not running.
Get-Service |
Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" } |
Select-Object Name, DisplayName, Status, StartType
When restarting a service, confirm the target first as well.
Get-Service -Name "Spooler"
Rehearse.
Restart-Service -Name "Spooler" -WhatIf
Service operations have a large impact, so confirm the maintenance window and recovery procedure before executing.
25. Viewing Event Logs
In Windows investigation, looking at event logs comes up frequently.
View the most recent 100 entries in the System log.
Get-WinEvent -LogName System -MaxEvents 100 |
Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message
Narrow to just errors and warnings.
Get-WinEvent -LogName System -MaxEvents 500 |
Where-Object { $_.LevelDisplayName -in @("Error", "Warning") } |
Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message
See only the errors from the last 24 hours.
$start = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{ LogName = "System"; StartTime = $start } |
Where-Object { $_.LevelDisplayName -eq "Error" } |
Select-Object TimeCreated, ProviderName, Id, Message
To keep investigation results in a CSV:
Get-WinEvent -LogName System -MaxEvents 500 |
Where-Object { $_.LevelDisplayName -in @("Error", "Warning") } |
Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message |
Export-Csv .\system-events.csv -NoTypeInformation -Encoding UTF8
Event logs easily grow large, so it is important to narrow the range with -MaxEvents or a time window.
26. Checking the Network
For reachability checks, use Test-Connection.
Test-Connection example.com -Count 4
To check TCP port reachability on Windows, Test-NetConnection is convenient.
Test-NetConnection example.com -Port 443
To check DNS resolution:
Resolve-DnsName example.com
In network investigation, isolate the problem like this:
Can the name be resolved
Can the IP be reached
Is the target port open
Is there interference from a proxy or firewall
Rather than judging everything with PowerShell alone, it works well as the entry point of the isolation process.
27. Looking at Web Results
For fetching web pages, use Invoke-WebRequest.
Invoke-WebRequest https://example.com |
Select-Object StatusCode, StatusDescription
For handling JSON API results, Invoke-RestMethod is convenient.
Invoke-RestMethod https://api.github.com/repos/PowerShell/PowerShell |
Select-Object full_name, stargazers_count, forks_count
API results can usually be handled as PowerShell objects from the start, which makes them easy to combine with Select-Object and Where-Object.
When investigating internal APIs too, start with read-only GET requests.
When handling credentials or tokens, be careful about screen display and what gets recorded in the transcript.
28. Measuring Execution Time — Measure-Command
When you want to know how long processing takes, use Measure-Command.
Measure-Command {
Get-ChildItem C:\Windows -File -Recurse -ErrorAction SilentlyContinue |
Measure-Object
}
The result includes TotalSeconds and TotalMilliseconds.
$result = Measure-Command {
Get-ChildItem . -File -Recurse | Measure-Object
}
$result.TotalSeconds
When you want to speed up a script, measuring time rather than going by feel is important. However, results vary with file counts, disk state, and network state, so do not judge from a single run — check several times.
29. Running Slow Work in the Background — Start-Job
To run a time-consuming investigation as a separate job, use Start-Job.
$job = Start-Job -ScriptBlock {
Get-ChildItem C:\Windows -File -Recurse -ErrorAction SilentlyContinue |
Measure-Object
}
View the job status.
Get-Job
Receive the results.
Receive-Job $job
Remove jobs that are no longer needed.
Remove-Job $job
Start-Job is convenient, but there is no need to use it heavily from the start. Run things normally first, and turn only the slow processing into jobs — that keeps things clear.
30. Using Command History
To see previously executed commands, use Get-History.
Get-History
Make just the command lines easy to read.
Get-History |
Select-Object Id, CommandLine
Re-run a specific history entry.
Invoke-History 12
History is convenient, but it can also re-run dangerous commands. When re-running change commands like Remove-Item or Stop-Process from history, check the content before executing.
31. Viewing Error Details — Get-Error
In PowerShell 7, Get-Error is available for looking at recent errors in detail.
Get-Error
To see only the most recent error message:
$Error[0].Exception.Message
When an error occurs, don’t just look at the red text on screen — check the following:
Which command failed
Which path or target it failed on
Whether it is a permissions problem
Whether the file does not exist
Whether it is a network or lock problem
To keep investigation results, combine with Start-Transcript and Export-Csv.
32. Frequently Used Comparison Operators
Comparison operators come up constantly with Where-Object.
| Operator | Meaning | Example |
|---|---|---|
-eq |
Equal | $_.Status -eq "Running" |
-ne |
Not equal | $_.Status -ne "Running" |
-gt |
Greater than | $_.Length -gt 10MB |
-ge |
Greater than or equal | $_.Length -ge 10MB |
-lt |
Less than | $_.Length -lt 10MB |
-le |
Less than or equal | $_.Length -le 10MB |
-like |
Wildcard match | $_.Name -like "*.log" |
-match |
Regular expression match | $_.Name -match "^app" |
-in |
The value is in a list | $_.Status -in @("Running", "Paused") |
-contains |
The list contains the value | @("a", "b") -contains "a" |
Examples:
Get-ChildItem . -File |
Where-Object { $_.Length -gt 10MB }
Get-Service |
Where-Object { $_.Status -in @("Running", "Paused") }
Get-ChildItem . -File |
Where-Object { $_.Name -match "\.log$" }
At first, -eq, -ne, -gt, -lt, and -like alone are enough. Once you are comfortable, -match and -in make conditions easier to write.
33. Small Practical Recipes
From here, these are examples in a form you can use directly in real work.
See file counts per extension
Get-ChildItem C:\Work -File -Recurse |
Group-Object -Property Extension -NoElement |
Sort-Object -Property Count -Descending
Use this when you want a rough grasp of a folder’s contents.
See the top 20 largest files
Get-ChildItem C:\Work -File -Recurse |
Sort-Object -Property Length -Descending |
Select-Object -First 20 FullName, @{Name="SizeMB"; Expression={ [math]::Round($_.Length / 1MB, 2) }}
Commonly used in disk space investigation.
See files modified in the last 24 hours
$since = (Get-Date).AddHours(-24)
Get-ChildItem C:\Work -File -Recurse |
Where-Object { $_.LastWriteTime -ge $since } |
Select-Object FullName, Length, LastWriteTime
Useful after an incident for seeing which files were modified.
Turn log lines containing ERROR into a CSV
Select-String -Path C:\App\Logs\*.log -Pattern "ERROR" |
Select-Object Path, LineNumber, Line |
Export-Csv .\error-lines.csv -NoTypeInformation -Encoding UTF8
Makes investigation results easier to share.
See 2 lines before and after each ERROR
Select-String -Path C:\App\Logs\*.log -Pattern "ERROR" -Context 2
Use this when you want the context around the cause.
See the processes using the most memory
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}
See services set to automatic start but stopped
Get-Service |
Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" } |
Select-Object Name, DisplayName, Status, StartType
Turn System log errors into a CSV
Get-WinEvent -LogName System -MaxEvents 500 |
Where-Object { $_.LevelDisplayName -eq "Error" } |
Select-Object TimeCreated, ProviderName, Id, Message |
Export-Csv .\system-errors.csv -NoTypeInformation -Encoding UTF8
Send command results to the clipboard
Get-Service |
Select-Object Name, DisplayName, Status |
ConvertTo-Csv -NoTypeInformation |
Set-Clipboard
Convenient for pasting into email or chat.
Compare file listings before and after work
Get-ChildItem C:\Work -File |
Select-Object -ExpandProperty Name |
Set-Content .\before.txt -Encoding UTF8
Take it again after the work.
Get-ChildItem C:\Work -File |
Select-Object -ExpandProperty Name |
Set-Content .\after.txt -Encoding UTF8
Compare.
Compare-Object (Get-Content .\before.txt) (Get-Content .\after.txt)
See a folder’s total size in GB
$size = Get-ChildItem C:\Work -File -Recurse |
Measure-Object -Property Length -Sum
[math]::Round($size.Sum / 1GB, 2)
34. Cautions When Combining with Change Commands
Most of what we have covered is read-only, and with those alone you can experiment fairly freely. These, on the other hand, are change commands.
| Operation | Command |
|---|---|
| Copy | Copy-Item |
| Move | Move-Item |
| Delete | Remove-Item |
| Rename | Rename-Item |
| Stop a process | Stop-Process |
| Restart a service | Restart-Service |
| Persist an environment variable | [Environment]::SetEnvironmentVariable() |
Use change commands in this order:
1. Look at the targets with Get-* commands
2. Filter with Where-Object
3. Review the target list with Select-Object
4. Count them with Measure-Object
5. Keep a record with Export-Csv if needed
6. Rehearse with -WhatIf where available
7. Execute
For example, deleting old .tmp files.
First, look at the targets.
$limit = (Get-Date).AddDays(-30)
$targets = Get-ChildItem C:\Temp -Filter *.tmp -File -Recurse |
Where-Object { $_.LastWriteTime -lt $limit }
$targets |
Select-Object FullName, Length, LastWriteTime
Count them.
$targets | Measure-Object
Keep them in a CSV.
$targets |
Select-Object FullName, Length, LastWriteTime |
Export-Csv .\delete-targets.csv -NoTypeInformation -Encoding UTF8
Confirm what would be deleted.
$targets | Remove-Item -WhatIf
If everything looks right, execute.
$targets | Remove-Item
Just sticking to this flow reduces accidents substantially.
35. How to Remember Them
Trying to memorize commands individually is hard, so it is easier to remember them by goal.
| Goal | Command to recall |
|---|---|
| Count | Measure-Object |
| Sum | Measure-Object -Sum |
| View by category | Group-Object |
| Remove duplicates | Sort-Object -Unique |
| Get just the values | Select-Object -ExpandProperty |
| Shape the columns | Select-Object |
| View largest first | Sort-Object -Descending |
| Search for strings | Select-String |
| See the surrounding lines | Select-String -Context |
| Compare two things | Compare-Object |
| Keep an audit trail | Export-Csv / Start-Transcript |
| Output to screen and file | Tee-Object |
| Send to the clipboard | Set-Clipboard |
| Measure time | Measure-Command |
| See error details | Get-Error |
36. Conclusion
PowerShell is powerful once you can write scripts. In real work, however, what you use most is, perhaps surprisingly, combinations of small commands.
Count
Sort
Group
Compare
Search
Extract
Save
Send to the clipboard
Keep a work log
Being able to do just these makes daily work considerably easier. There is no need to aim for difficult automation from the start.
First become able to see the situation accurately with read-only commands, and on top of that, use change commands like Copy-Item, Move-Item, Remove-Item, and Restart-Service only when needed.
The trick to using PowerShell safely is this order:
Look -> Count -> Shape -> Record -> Rehearse -> Execute
Internalize this pattern, and PowerShell stops being “a black screen where you type commands” and becomes a practical tool supporting your daily investigation, organization, and reporting.
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
PowerShell Command Basics — The Operations to Learn First and How to Use Them Safely
So that PowerShell beginners never get lost in real work, this article covers how to find cmdlets, the pipeline, file operations, CSV pro...
How to Run PowerShell from C# (CSharp) and Receive the Results as Objects
How to launch PowerShell from C# and receive results as PSObject rather than strings — a practical walkthrough of the PowerShell SDK, Add...
Testing PowerShell with Pester — A Practical Approach to Making Operations Scripts Harder to Break
A practical walkthrough of testing PowerShell scripts with Pester v5 — safely covering date handling, file operations, deletion logic, mo...
Applied PowerShell Scripting — Safely Automating Log Investigation, Archiving, and Reporting
Practical steps for safely automating log investigation, CSV reporting, archiving old logs, keeping audit trails, and Task Scheduler exec...
Preparing for VBScript Deprecation: An Audit Guide for VBA and Internal Tools
Preparing for the phased deprecation of VBScript: inventorying VBA, Excel macros, and internal tools, static detection, execution logging...
Related Topics
These topic pages place the article in a broader service and decision context.
Windows Technical Topics
Topic hub for KomuraSoft LLC's Windows development, investigation, and legacy-asset articles.
Where This Topic Connects
This article connects naturally to the following service pages.
Windows App Development
We support Windows desktop applications that involve resident processing, device integration, operational logging, and maintainable structure.
Author Profile
Profile page for the article author.
Go Komura
Representative of KomuraSoft LLC
Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.
Public links