PowerShell Select-Object: Complete Guide with Examples [2024]
The Select-Object cmdlet is one of PowerShell’s most essential tools for working with objects. It allows you to select specific properties, filter items, create calculated properties, and transform data as it moves through the pipeline.
Whether you’re working with processes, files, Active Directory users, or any PowerShell object, Select-Object gives you precise control over which data to keep, modify, or discard.
In this comprehensive guide, we’ll cover everything you need to know about PowerShell Select-Object, from basic property selection to advanced calculated properties and performance optimization.
Table of Contents
- What is Select-Object?
- Why Use Select-Object?
- Select-Object Syntax
- Selecting Properties
- Selecting Items
- Calculated Properties
- ExpandProperty Parameter
- Selecting Nested Properties
- Select Value Only
- Select-Object vs Where-Object
- Select-Object vs Format-Table
- Performance Optimization
- Real-World Use Cases
- Common Mistakes
- Best Practices
- Troubleshooting
- FAQs
- Conclusion
- Related Articles
What is Select-Object? {#what-is-select-object}
Select-Object (alias: select) is a PowerShell cmdlet that selects specified properties of objects and can also select a subset of items from a collection. It’s primarily used for:
- Selecting specific properties from objects
- Filtering the first, last, or unique items
- Creating custom calculated properties
- Expanding nested property values
- Reducing memory usage by limiting selected data
Key Characteristics:
- Works with any PowerShell object
- Pipeline-friendly (receives and outputs objects)
- Non-destructive (doesn’t modify original objects)
- Can combine multiple selection operations
- Supports wildcards in property names
Why Use Select-Object? {#why-use-select-object}
Select-Object is essential for:
- Reducing visual clutter - Display only relevant properties
- Improving performance - Process only needed data
- Creating custom views - Rename or calculate properties
- Exporting data - Select fields for CSV/JSON export
- Pipeline optimization - Pass minimal data between cmdlets
- Memory efficiency - Limit large collections
Without Select-Object:
Get-Process
# Returns all 60+ properties, overwhelming output
With Select-Object:
Get-Process | Select-Object Name, CPU, Memory -First 10
# Clean, focused output with only what you need
Select-Object Syntax {#syntax}
Basic Syntax
Select-Object [-Property] <property names> [parameters]
Common Parameters
| Parameter | Description | Example |
|---|---|---|
-Property | Properties to select | -Property Name, CPU |
-ExcludeProperty | Properties to exclude | -ExcludeProperty StartTime |
-ExpandProperty | Expand nested property | -ExpandProperty ProcessName |
-First | Select first N items | -First 10 |
-Last | Select last N items | -Last 5 |
-Skip | Skip first N items | -Skip 20 |
-Unique | Select unique values | -Unique |
-Wait | Wait for objects (remote) | -Wait |
-Index | Select by index | -Index 0,2,4 |
Selecting Properties {#selecting-properties}
Select Single Property {#select-single}
Get-Process | Select-Object Name
Output:
Name
----
ApplicationFrameHost
audiodg
brave
chrome
Code
Note: Returns objects with only the Name property, not just strings.
Select Multiple Properties {#select-multiple}
Get-Process | Select-Object Name, Id, CPU -First 5
Output:
Name Id CPU
---- -- ---
ApplicationFrameHost 1234 0.5
armsvc 5678 0.1
audiodg 9012 2.3
brave 3456 15.7
brave 7890 12.4
Using Property Array
$properties = @("Name", "Id", "CPU", "WorkingSet")
Get-Process | Select-Object -Property $properties -First 10
Select All Properties (*) {#select-all}
# Select all properties (use with caution on large objects)
Get-Process chrome | Select-Object *
When to use:
- Exploring object structure
- Debugging scripts
- Finding hidden properties
When NOT to use:
- Performance-critical scripts
- Processing many objects
- Exporting to CSV (too many columns)
Exclude Properties {#exclude-properties}
# Select all properties except ProcessName and Id
Get-Process | Select-Object * -ExcludeProperty ProcessName, Id -First 5
Practical example - Remove sensitive properties:
Get-ADUser john.doe -Properties * |
Select-Object * -ExcludeProperty userPassword, pwdLastSet
Selecting Items {#selecting-items}
First N Items (-First) {#first-items}
# Get first 10 processes
Get-Process | Select-Object Name, CPU -First 10
Real-world example - Top 5 CPU consumers:
Get-Process | Sort-Object CPU -Descending | Select-Object Name, CPU -First 5
Output:
Name CPU
---- ---
chrome 234.56
Code 187.34
brave 156.12
Teams 134.78
Outlook 98.45
Last N Items (-Last) {#last-items}
# Get last 5 log entries
Get-Content C:\Logs\app.log | Select-Object -Last 5
Example - Most recent files:
Get-ChildItem C:\Data | Sort-Object LastWriteTime | Select-Object Name, LastWriteTime -Last 10
Skip Items (-Skip) {#skip-items}
# Skip first 10 items, then get next 5
Get-Process | Select-Object Name, CPU -Skip 10 -First 5
Pagination example:
$pageSize = 20
$page = 2
Get-ADUser -Filter * |
Select-Object Name, EmailAddress -Skip (($page - 1) * $pageSize) -First $pageSize
Combining First, Skip, and Last
# Skip first 5, get next 10
Get-ChildItem C:\Logs | Select-Object Name -Skip 5 -First 10
# Get all except first 3 and last 2
$files = Get-ChildItem C:\Data
$files | Select-Object -Skip 3 -First ($files.Count - 5)
Unique Items (-Unique) {#unique-items}
# Get unique process names
Get-Process | Select-Object -Property ProcessName -Unique
Example - Unique file extensions:
Get-ChildItem C:\Data -Recurse |
Select-Object -Property Extension -Unique |
Sort-Object Extension
Output:
Extension
---------
.css
.html
.js
.json
.md
.txt
Important: -Unique only works on selected properties, not the entire object.
Calculated Properties {#calculated-properties}
Calculated properties allow you to create custom properties on-the-fly:
Basic Calculated Property Syntax
@{
Name = 'PropertyName'
Expression = { <calculation> }
}
# Or shorter:
@{N='PropertyName'; E={ <calculation> }}
# Or shortest:
@{l='PropertyName'; e={ <calculation> }}
Example 1: Convert Bytes to MB
Get-ChildItem C:\Data |
Select-Object Name,
@{Name='SizeMB'; Expression={[Math]::Round($_.Length / 1MB, 2)}}
Output:
Name SizeMB
---- ------
report.xlsx 15.34
data.csv 2.56
archive.zip 234.12
Example 2: Format Dates
Get-Process |
Select-Object Name,
@{N='StartTime'; E={$_.StartTime.ToString('yyyy-MM-dd HH:mm:ss')}} -First 5
Example 3: Combine Properties
Get-ADUser -Filter * -Properties GivenName, Surname |
Select-Object @{N='FullName'; E={"$($_.GivenName) $($_.Surname)"}},
SamAccountName,
Enabled
Output:
FullName SamAccountName Enabled
-------- -------------- -------
John Doe john.doe True
Jane Smith jane.smith True
Bob Wilson bob.wilson False
Example 4: Conditional Logic in Calculated Properties
Get-Service |
Select-Object Name,
Status,
@{N='StatusIcon'; E={
if ($_.Status -eq 'Running') { '✓' }
elseif ($_.Status -eq 'Stopped') { '✗' }
else { '?' }
}}
Example 5: Multiple Calculations
Get-Process |
Select-Object Name,
@{N='CPU(s)'; E={[Math]::Round($_.CPU, 2)}},
@{N='Memory(MB)'; E={[Math]::Round($_.WorkingSet / 1MB, 2)}},
@{N='Status'; E={
if ($_.Responding) { 'Responding' } else { 'Not Responding' }
}} |
Sort-Object 'Memory(MB)' -Descending |
Select-Object -First 10
Example 6: Nested Property Access
Get-WmiObject Win32_LogicalDisk |
Select-Object DeviceID,
@{N='FreeSpace(GB)'; E={[Math]::Round($_.FreeSpace / 1GB, 2)}},
@{N='TotalSize(GB)'; E={[Math]::Round($_.Size / 1GB, 2)}},
@{N='FreePercent'; E={[Math]::Round(($_.FreeSpace / $_.Size) * 100, 2)}}
ExpandProperty Parameter {#expandproperty}
-ExpandProperty extracts the value from a property instead of returning an object:
Without ExpandProperty
Get-Process chrome | Select-Object Name
Output:
Name
----
chrome
Returns: Object with Name property
With ExpandProperty
Get-Process chrome | Select-Object -ExpandProperty Name
Output:
chrome
Returns: String value directly
Practical Examples
Example 1: Get list of service names:
$serviceNames = Get-Service | Select-Object -ExpandProperty Name
# $serviceNames is now a simple array of strings
Example 2: Expand nested collections:
Get-ADUser john.doe -Properties MemberOf |
Select-Object -ExpandProperty MemberOf
Output:
CN=Administrators,CN=Builtin,DC=contoso,DC=com
CN=Domain Admins,CN=Users,DC=contoso,DC=com
CN=IT Staff,OU=Groups,DC=contoso,DC=com
Example 3: Combine with other properties:
# This WON'T work (can't combine ExpandProperty with other properties):
Get-Process | Select-Object Name, -ExpandProperty ProcessName # ERROR
# Instead, use calculated properties:
Get-Process | Select-Object @{N='NameExpanded'; E={$_.Name}}, Id, CPU
When to Use -ExpandProperty
Use when:
- You need simple values (strings, numbers)
- Exporting to text files
- Passing values to other commands
- Working with nested collections
Don’t use when:
- You need multiple properties
- You want to keep object structure
- Exporting to CSV (use regular property selection)
Selecting Nested Properties {#nested-properties}
Access properties within properties using dot notation:
Example 1: File System Properties
Get-ChildItem C:\Data |
Select-Object Name,
Length,
@{N='CreationYear'; E={$_.CreationTime.Year}},
@{N='ModifiedMonth'; E={$_.LastWriteTime.ToString('MMMM')}}
Example 2: Process Module Information
Get-Process explorer |
Select-Object Name,
@{N='MainModule'; E={$_.MainModule.FileName}},
@{N='ModuleVersion'; E={$_.MainModule.FileVersionInfo.FileVersion}}
Example 3: AD User Manager Information
Get-ADUser john.doe -Properties Manager |
Select-Object Name,
@{N='ManagerName'; E={
if ($_.Manager) {
(Get-ADUser $_.Manager).Name
} else {
'No Manager'
}
}}
Example 4: Complex Nested Access
Get-WmiObject Win32_NetworkAdapterConfiguration -Filter "IPEnabled=True" |
Select-Object Description,
@{N='IPAddress'; E={$_.IPAddress[0]}},
@{N='SubnetMask'; E={$_.IPSubnet[0]}},
@{N='Gateway'; E={$_.DefaultIPGateway[0]}}
Select Value Only {#select-value-only}
Get raw values without property names:
Method 1: ExpandProperty
# Get just the names
Get-Service | Where-Object Status -eq 'Running' | Select-Object -ExpandProperty Name
Method 2: ForEach-Object
# Alternative approach
Get-Service | Where-Object Status -eq 'Running' | ForEach-Object { $_.Name }
Method 3: Property Access
# Direct property access
$services = Get-Service | Where-Object Status -eq 'Running'
$services.Name
Practical Example: Build String Array
# Get all .txt files as string array
$textFiles = Get-ChildItem C:\Data -Filter "*.txt" | Select-Object -ExpandProperty FullName
# Use in further operations
foreach ($file in $textFiles) {
Write-Host "Processing: $file"
# Do something with each file path
}
Select-Object vs Where-Object {#select-vs-where}
Common confusion: When to use Select-Object vs Where-Object?
Where-Object: Filters objects (rows)
# Filter: Keep only processes using > 100 MB
Get-Process | Where-Object { $_.WorkingSet -gt 100MB }
Select-Object: Selects properties (columns) and items
# Select: Choose which properties to display
Get-Process | Select-Object Name, CPU, WorkingSet
Combined Usage
# Filter THEN select
Get-Process |
Where-Object { $_.CPU -gt 10 } |
Select-Object Name, CPU, WorkingSet -First 10
Comparison Table
| Feature | Where-Object | Select-Object |
|---|---|---|
| Purpose | Filter objects | Select properties/items |
| What it filters | Rows (objects) | Columns (properties) + items |
| Output | Filtered objects | Objects with selected properties |
| When to use | ”Show me processes WHERE CPU > 10" | "SELECT Name, CPU properties” |
Select-Object vs Format-Table {#select-vs-format}
Critical difference: Format cmdlets should only be used for display, not for processing.
Format-Table: Display only
# This breaks the pipeline - DON'T pass to other cmdlets!
Get-Process | Format-Table Name, CPU | Where-Object CPU -gt 10 # ERROR
Select-Object: Processing + display
# This works - can continue pipeline
Get-Process | Select-Object Name, CPU | Where-Object CPU -gt 10 # OK
Best Practice
# ✅ GOOD: Select first, process, then format at END
Get-Process |
Select-Object Name, CPU, WorkingSet |
Where-Object CPU -gt 10 |
Sort-Object CPU -Descending |
Format-Table -AutoSize # Format LAST
# ❌ BAD: Format in the middle
Get-Process |
Format-Table Name, CPU | # This breaks everything after
Where-Object CPU -gt 10 # Will fail
Performance Optimization {#performance}
Tip 1: Select Early in Pipeline
# Slower - processes all properties through pipeline
Get-Process | Where-Object CPU -gt 10 | Select-Object Name, CPU
# Faster - reduces data early
Get-Process | Select-Object Name, CPU | Where-Object CPU -gt 10
Tip 2: Use -First to Limit Results
# Slower - processes all, then takes first 10
Get-ChildItem C:\Windows -Recurse | Select-Object Name -First 10
# Faster - stops after finding 10
Get-ChildItem C:\Windows -Recurse | Select-Object Name -First 10
Tip 3: Avoid Select * When Possible
# Slower - retrieves all 60+ properties
Get-Process | Select-Object * | Where-Object CPU -gt 10
# Faster - only gets needed properties
Get-Process | Select-Object Name, CPU | Where-Object CPU -gt 10
Tip 4: Use -Property for Specific Cmdlets
# Slower - retrieves all AD properties then selects
Get-ADUser -Filter * | Select-Object Name, EmailAddress
# Faster - only retrieves needed properties
Get-ADUser -Filter * -Properties EmailAddress | Select-Object Name, EmailAddress
Performance Benchmark
# Test 1: Select all properties
Measure-Command {
Get-Process | Select-Object * | Out-Null
}
# Test 2: Select specific properties
Measure-Command {
Get-Process | Select-Object Name, Id, CPU | Out-Null
}
# Test 3: Select with -First
Measure-Command {
Get-Process | Select-Object Name, Id, CPU -First 10 | Out-Null
}
Typical Results:
Test 1 (Select *): 450ms
Test 2 (Specific): 120ms
Test 3 (With -First): 15ms
Real-World Use Cases {#use-cases}
1. Selecting AD User Properties {#ad-users}
# Get AD users with specific properties formatted for report
Get-ADUser -Filter {Enabled -eq $true} -Properties Department, EmailAddress, Manager |
Select-Object Name,
SamAccountName,
EmailAddress,
Department,
@{N='ManagerName'; E={
if ($_.Manager) {
(Get-ADUser $_.Manager).Name
} else {
'No Manager'
}
}},
@{N='Status'; E={if ($_.Enabled) {'Active'} else {'Disabled'}}} |
Sort-Object Department, Name |
Export-Csv "C:\Reports\ActiveUsers.csv" -NoTypeInformation
2. Filtering Large File Lists {#file-lists}
# Find large files with detailed info
Get-ChildItem C:\Data -Recurse -File |
Select-Object Name,
@{N='SizeGB'; E={[Math]::Round($_.Length / 1GB, 3)}},
@{N='Extension'; E={$_.Extension.ToUpper()}},
@{N='AgeInDays'; E={((Get-Date) - $_.LastWriteTime).Days}},
@{N='Path'; E={$_.DirectoryName}},
LastWriteTime |
Where-Object SizeGB -gt 1 |
Sort-Object SizeGB -Descending |
Select-Object -First 20 |
Format-Table -AutoSize
3. Creating Custom Reports {#custom-reports}
# System inventory report
$report = Get-WmiObject Win32_LogicalDisk |
Where-Object DriveType -eq 3 |
Select-Object DeviceID,
@{N='TotalGB'; E={[Math]::Round($_.Size / 1GB, 2)}},
@{N='FreeGB'; E={[Math]::Round($_.FreeSpace / 1GB, 2)}},
@{N='UsedGB'; E={[Math]::Round(($_.Size - $_.FreeSpace) / 1GB, 2)}},
@{N='FreePercent'; E={[Math]::Round(($_.FreeSpace / $_.Size) * 100, 1)}},
@{N='Status'; E={
$freePercent = ($_.FreeSpace / $_.Size) * 100
if ($freePercent -lt 10) { 'Critical' }
elseif ($freePercent -lt 20) { 'Warning' }
else { 'OK' }
}}
$report | Format-Table -AutoSize
$report | Export-Csv "C:\Reports\DiskSpace.csv" -NoTypeInformation
4. Working with Process Data {#process-data}
# Top CPU and memory consumers
$processes = Get-Process |
Select-Object Name,
Id,
@{N='CPU(s)'; E={[Math]::Round($_.CPU, 2)}},
@{N='Memory(MB)'; E={[Math]::Round($_.WorkingSet / 1MB, 2)}},
@{N='Threads'; E={$_.Threads.Count}},
@{N='Handles'; E={$_.HandleCount}},
@{N='Status'; E={if ($_.Responding) {'Running'} else {'Not Responding'}}} |
Where-Object 'CPU(s)' -gt 1 |
Sort-Object 'Memory(MB)' -Descending
# Top 10 by memory
Write-Host "`n=== Top 10 Memory Consumers ===" -ForegroundColor Cyan
$processes | Select-Object -First 10 | Format-Table -AutoSize
# Top 10 by CPU
Write-Host "`n=== Top 10 CPU Consumers ===" -ForegroundColor Cyan
$processes | Sort-Object 'CPU(s)' -Descending | Select-Object -First 10 | Format-Table -AutoSize
5. Exporting to CSV {#export-csv}
# Export service information
Get-Service |
Select-Object Name,
DisplayName,
Status,
StartType,
@{N='CanStop'; E={$_.CanStop}},
@{N='CanPause'; E={$_.CanPauseAndContinue}},
@{N='DependentServices'; E={$_.DependentServices.Count}},
@{N='ServicesDependedOn'; E={$_.ServicesDependedOn.Count}} |
Export-Csv "C:\Reports\Services.csv" -NoTypeInformation
Write-Host "Service data exported successfully"
# Import and display summary
$services = Import-Csv "C:\Reports\Services.csv"
Write-Host "`nTotal Services: $($services.Count)"
Write-Host "Running: $($services | Where-Object Status -eq 'Running' | Measure-Object | Select-Object -ExpandProperty Count)"
Write-Host "Stopped: $($services | Where-Object Status -eq 'Stopped' | Measure-Object | Select-Object -ExpandProperty Count)"
Common Mistakes {#common-mistakes}
1. Using Format-Table Before Pipeline Operations
❌ Wrong:
Get-Process | Format-Table Name, CPU | Where-Object CPU -gt 10 # ERROR!
✅ Correct:
Get-Process | Where-Object CPU -gt 10 | Format-Table Name, CPU
2. Confusing Select-Object with Where-Object
❌ Wrong:
# Trying to filter with Select-Object
Get-Process | Select-Object {$_.CPU -gt 10} # Doesn't filter!
✅ Correct:
Get-Process | Where-Object CPU -gt 10 | Select-Object Name, CPU
3. Combining -ExpandProperty with Other Properties
❌ Wrong:
Get-Process | Select-Object Name, -ExpandProperty ProcessName # ERROR
✅ Correct:
# Use calculated property instead
Get-Process | Select-Object @{N='ProcessName'; E={$_.Name}}, Id, CPU
4. Not Using Quotes for Calculated Property Names with Spaces
❌ Wrong:
Select-Object @{N=Size MB; E={$_.Length / 1MB}} # ERROR
✅ Correct:
Select-Object @{N='Size MB'; E={$_.Length / 1MB}}
5. Forgetting to Access Property Value in Calculated Expression
❌ Wrong:
Select-Object @{N='UpperName'; E={Name.ToUpper()}} # ERROR - missing $_
✅ Correct:
Select-Object @{N='UpperName'; E={$_.Name.ToUpper()}}
6. Using Select * Unnecessarily
❌ Inefficient:
Get-Process | Select-Object * | Export-Csv file.csv # Too many columns!
✅ Efficient:
Get-Process | Select-Object Name, Id, CPU, WorkingSet | Export-Csv file.csv
7. Not Understanding -Unique Behavior
❌ Misunderstanding:
# This doesn't make objects unique, only the selected property
Get-Process | Select-Object Name -Unique
✅ Understanding:
# Gets unique process names (may still have duplicate Name values if other properties differ)
Get-Process | Select-Object -Property Name -Unique
Best Practices {#best-practices}
1. Select Early, Format Late
# ✅ GOOD: Select → Process → Format
Get-Process |
Select-Object Name, CPU, WorkingSet |
Where-Object CPU -gt 10 |
Sort-Object CPU -Descending |
Format-Table -AutoSize # Format LAST
2. Be Specific with Property Selection
# ❌ Avoid: Select everything
Get-ADUser -Filter * | Select-Object *
# ✅ Better: Select only what you need
Get-ADUser -Filter * -Properties EmailAddress |
Select-Object Name, SamAccountName, EmailAddress
3. Use Meaningful Names for Calculated Properties
# ❌ Unclear
Select-Object @{N='Prop1'; E={$_.Length / 1MB}}
# ✅ Clear
Select-Object @{N='SizeMB'; E={[Math]::Round($_.Length / 1MB, 2)}}
4. Combine Select-Object with Sort-Object
# Get top 10 largest files
Get-ChildItem C:\Data -Recurse |
Select-Object Name, Length, LastWriteTime |
Sort-Object Length -Descending |
Select-Object -First 10
5. Use -First for Large Collections
# ✅ Efficient: Stops processing after 100 items
Get-ChildItem C:\Windows -Recurse | Select-Object Name -First 100
# ❌ Inefficient: Processes all items then takes 100
Get-ChildItem C:\Windows -Recurse | Select-Object -First 100 Name
6. Document Complex Calculated Properties
Get-Process | Select-Object Name,
# Calculate CPU percentage of total system CPU time
@{N='CPUPercent'; E={
$totalCPU = (Get-Process | Measure-Object CPU -Sum).Sum
if ($totalCPU -gt 0) {
[Math]::Round(($_.CPU / $totalCPU) * 100, 2)
} else {
0
}
}}
7. Use Consistent Aliasing
# Both work, be consistent:
# Full form (more readable in scripts)
Select-Object Name, CPU
# Alias (faster for interactive use)
Select Name, CPU
Troubleshooting {#troubleshooting}
Issue 1: “Property does not exist”
Cause: Trying to select a property that doesn’t exist
Solution:
# Check available properties first
Get-Process | Get-Member -MemberType Property
# Or use Select-Object * to see all
Get-Process | Select-Object * -First 1
Issue 2: Calculated Property Returns Null
Cause: Incorrect syntax or missing $_ reference
Solution:
# ❌ Wrong: Missing $_
Select-Object @{N='Size'; E={Length / 1MB}}
# ✅ Correct: Include $_
Select-Object @{N='Size'; E={$_.Length / 1MB}}
Issue 3: -Unique Not Working as Expected
Cause: -Unique works on selected properties only, not entire object
Solution:
# To get truly unique objects based on property
Get-Process |
Select-Object ProcessName |
Sort-Object ProcessName -Unique # Use Sort-Object -Unique instead
Issue 4: Output Looks Wrong After Format-Table
Cause: Format-Table was used mid-pipeline
Solution:
# ❌ Wrong: Format in middle
Get-Process | Format-Table | Select-Object -First 10 # ERROR
# ✅ Correct: Format at end
Get-Process | Select-Object -First 10 | Format-Table
Issue 5: Performance Issues with Large Collections
Cause: Processing too many objects or properties
Solution:
# ✅ Use -First to limit early
Get-ChildItem C:\Windows -Recurse |
Select-Object Name, Length -First 1000
# ✅ Select fewer properties
Get-Process | Select-Object Name, CPU # Instead of Select-Object *
FAQs {#faqs}
Q1: What’s the difference between Select-Object and Where-Object?
A: Select-Object chooses which properties (columns) and items to include, while Where-Object filters which objects (rows) to keep based on conditions.
Q2: Can I rename properties with Select-Object?
A: Yes, use calculated properties:
Select-Object @{N='NewName'; E={$_.OldName}}
Q3: How do I select the first 10 items?
A: Use -First 10:
Get-Process | Select-Object Name, CPU -First 10
Q4: What does -ExpandProperty do?
A: It extracts the value from a property instead of returning an object with that property.
Q5: Can I use wildcards in property names?
A: Yes:
Get-Process | Select-Object Name, *Memory*
Q6: How do I select unique values?
A: Use -Unique:
Get-Process | Select-Object ProcessName -Unique
Q7: Why does my calculated property show an error?
A: Most likely missing $_ to reference the current object:
Select-Object @{N='Size'; E={$_.Length}} # Don't forget $_ !
Q8: Can I select properties from nested objects?
A: Yes, use calculated properties to access nested values:
Select-Object @{N='Year'; E={$_.CreationTime.Year}}
Q9: How do I select all properties except one?
A: Use -ExcludeProperty:
Select-Object * -ExcludeProperty PropertyName
Q10: What’s the difference between Select-Object and Format-Table?
A: Select-Object filters data and can be used mid-pipeline, while Format-Table is for display only and should be the last cmdlet.
Q11: Can I use Select-Object without a pipeline?
A: Yes, with -InputObject:
Select-Object -InputObject $object -Property Name, Value
Q12: How do I select items by index?
A: Use -Index:
Get-Process | Select-Object -Index 0,2,4,6,8
Q13: Why is my CSV export showing wrong data?
A: Make sure to use Select-Object before Export-Csv, not Format-Table:
Get-Process | Select-Object Name, CPU | Export-Csv file.csv # ✅
Get-Process | Format-Table Name, CPU | Export-Csv file.csv # ❌
Q14: Can I use multiple calculated properties?
A: Yes, separate them with commas:
Select-Object Name, @{N='Prop1'; E={...}}, @{N='Prop2'; E={...}}
Q15: How do I skip the first N items?
A: Use -Skip:
Get-Process | Select-Object Name -Skip 10 -First 5
Conclusion {#conclusion}
PowerShell Select-Object is an essential cmdlet for working with objects in the pipeline. It provides powerful capabilities for selecting properties, filtering items, creating calculated properties, and transforming data for reports and exports.
Key Takeaways:
- Use
Select-Objectto choose properties (columns) and items from collections - Select early in the pipeline to improve performance
- Use calculated properties to create custom fields
-ExpandPropertyextracts values directly without object wrapper- Combine with
Sort-Objectand-Firstfor top N queries - Format cmdlets should always come last in the pipeline
- Select-Object returns objects, not formatted text
Next Steps:
- Practice with calculated properties for custom reports
- Combine Select-Object with Where-Object for precise data filtering
- Use -First and -Last for pagination and sampling
- Explore nested property access for complex objects
- Master performance optimization techniques for large datasets
For more pipeline and filtering techniques, see our guides on PowerShell Where-Object, PowerShell ForEach-Object, and PowerShell Sort-Object.
Related Articles {#related-articles}
Core Pipeline & Filtering
- PowerShell Where-Object - Filter before selecting
- PowerShell ForEach-Object - Process selected data
- PowerShell Get-ChildItem Filter - Filter files early
Data Structures
- PowerShell Arrays - Work with filtered arrays
- PowerShell Hashtables - Select from hashtable collections
- PowerShell Variables - Store selected values
- PowerShell Strings - String manipulation in expressions
Sorting & Output
- PowerShell Sort-Object - Sort selected data
- PowerShell Format Table - Format output
- PowerShell Output Table - Display results
- PowerShell Group-Object - Group selected data
File Operations
- PowerShell Get-Content - Read and select from files
- PowerShell Output to File - Output selected data
- PowerShell Get File Properties - Select file metadata
- PowerShell Delete Files - Delete selected files
- PowerShell List Files - Select from file listings
Data Export & Conversion
- PowerShell Export CSV - Export selected data to CSV
- PowerShell Import CSV - Select from CSV imports
- PowerShell Add-Member - Add to selected objects
- PowerShell Convert Operations - Convert selected data types
Control Flow & Logic
- PowerShell If-Else Statement - Conditional selection
- PowerShell Switch Statement - Switch-based logic
- PowerShell Try-Catch - Error handling in expressions
Functions & Organization
- PowerShell Functions - Create selection functions
- PowerShell Measure-Object - Analyze selected data
- PowerShell Group-Object - Group selected items
Active Directory & System
- PowerShell Active Directory Guide - Select AD properties
- PowerShell AD Security Guide - Select security data
- PowerShell Get-ADUser - Select user properties
- PowerShell Get-Process - Select process information
- PowerShell Get CPU Usage - Select performance data
- PowerShell Get Memory Usage - Select memory metrics
- DSACLS Permission Management - Select permission data
Date & Time
- PowerShell DateTime Format - Format in calculated properties
- PowerShell DateTime Operations - Date calculations in selection
Performance & Optimization
- PowerShell Performance Tuning - Optimize selection performance
- PowerShell Benchmarking - Measure selection speed
Comprehensive Guides
- Complete PowerShell Guide - Full PowerShell selection techniques
- Complete PowerShell Tutorial - Comprehensive course
- PowerShell Tutorial Complete - Full tutorial