PowerShell Formatting Output

PowerShell returns objects, not plain text. When you run a cmdlet, PowerShell decides how to display those objects based on built-in formatting rules. You can override this behavior at any time using formatting cmdlets to shape output into tables, lists, wide columns, or raw data — exactly the way you need it.

Why Formatting Matters

Without formatting:
Get-Service
→ Dumps a wall of text with every property

With formatting:
Get-Service | Format-Table Name, Status -AutoSize
→ Clean two-column table, easy to scan
PowerShell's four main formatting cmdlets each serve a different purpose:
Format-Table  → Grid/table layout (columns and rows)
Format-List   → Property-per-line layout (detail view)
Format-Wide   → One property spread across columns
Format-Custom → Fully customized display

Format-Table (ft)

Format-Table displays objects as a table with each property as a column. It is the most commonly used formatting cmdlet.
# Basic table
Get-Service | Format-Table Name, Status, StartType

# Auto-size columns to fit content
Get-Service | Format-Table Name, Status -AutoSize

# Wrap long values instead of truncating
Get-Process | Format-Table Name, CPU, Description -Wrap

Custom Column Headers

Get-Process | Format-Table `
    @{Label="Process Name"; Expression={$_.Name}},
    @{Label="CPU Used"; Expression={[math]::Round($_.CPU, 2)}},
    @{Label="Memory (MB)"; Expression={[math]::Round($_.WorkingSet64 / 1MB, 1)}}

Sample Output

Process Name    CPU Used    Memory (MB)
------------    --------    -----------
explorer        12.34       102.5
chrome          45.21       512.3
powershell       2.11        88.0

Format-List (fl)

Format-List shows each property on its own line. Use it when you need to see all details of a single object.
# Show all properties of one service
Get-Service -Name "WinDefend" | Format-List *

# Show specific properties in list view
Get-Process -Name "chrome" | Format-List Name, Id, CPU, WorkingSet64

Sample Output

Name         : chrome
Id           : 5432
CPU          : 45.21
WorkingSet64 : 537395200

Format-Wide (fw)

Format-Wide spreads one property across multiple columns — useful for scanning a large number of names quickly.
# List all process names in 3 columns
Get-Process | Format-Wide Name -Column 3

# List service names in 4 columns
Get-Service | Format-Wide Name -Column 4

Sample Output

AdobeUpdater    chrome          explorer
notepad         OneDrive        powershell
SearchHost      svchost         taskhostw

Comparing Format-Table vs Format-List

+------------------------+     +------------------------+
|    Format-Table        |     |    Format-List         |
|                        |     |                        |
| Name    Status  Type   |     | Name    : Spooler      |
| ------  ------  ----   |     | Status  : Running      |
| Spooler Running Auto   |     | Type    : Automatic    |
| BITS    Stopped Man    |     |                        |
|                        |     | Name    : BITS         |
| (good for many items)  |     | Status  : Stopped      |
+------------------------+     | (good for one item)    |
                               +------------------------+

Select-Object — Choose Properties Before Formatting

Use Select-Object before a Format cmdlet to pick exactly which properties appear. This also controls the column order.
Get-Process |
    Select-Object Name, Id, CPU |
    Format-Table -AutoSize
# Select the top 5 processes by memory
Get-Process |
    Sort-Object WorkingSet64 -Descending |
    Select-Object -First 5 Name, WorkingSet64 |
    Format-Table -AutoSize

Out-GridView — Interactive Table in a Window

Out-GridView opens a resizable, searchable, filterable pop-up table — perfect for quick interactive exploration.
# Browse all services interactively
Get-Service | Out-GridView

# Select items from the grid and pass them to another cmdlet
Get-Process | Out-GridView -PassThru | Stop-Process

Formatting Numbers and Dates in Output

# Format file sizes as MB
Get-ChildItem "C:\Windows" |
    Select-Object Name,
        @{Label="Size (MB)"; Expression={[math]::Round($_.Length / 1MB, 2)}} |
    Format-Table -AutoSize

# Format dates
Get-ChildItem "C:\Temp" |
    Select-Object Name,
        @{Label="Modified"; Expression={$_.LastWriteTime.ToString("yyyy-MM-dd")}} |
    Format-Table -AutoSize

Output Destinations

PowerShell can send formatted output to different destinations:
CmdletDestinationExample
Out-HostScreen (default)Get-Process | Out-Host
Out-FileText fileGet-Service | Out-File "services.txt"
Out-GridViewInteractive windowGet-Process | Out-GridView
Out-PrinterPrinterGet-Service | Out-Printer
Out-NullDiscard outputGet-Process | Out-Null
Out-StringConverts to stringGet-Service | Out-String

Saving Formatted Output to a File

# Save a formatted service report to a text file
Get-Service |
    Format-Table Name, Status, StartType -AutoSize |
    Out-File "C:\Reports\services.txt"

# Append to an existing file
Get-Service |
    Format-Table Name, Status -AutoSize |
    Out-File "C:\Reports\services.txt" -Append

Important Rule — Format Last

Always apply formatting at the end of a pipeline. Formatting cmdlets convert objects into display-only text. Once formatted, the data can no longer be filtered, sorted, or exported properly.
# WRONG — Formatting before filtering
Get-Service | Format-Table Name, Status | Where-Object Status -eq "Running"
# Error: Where-Object cannot filter formatted text

# CORRECT — Filter and sort first, format last
Get-Service |
    Where-Object Status -eq "Running" |
    Sort-Object Name |
    Format-Table Name, Status -AutoSize
Pipeline Rule:
Get data → Filter → Sort → Select properties → Format → Output

Summary

PowerShell's formatting cmdlets give full control over how output looks. Format-Table suits multi-record grids, Format-List works best for inspecting single objects, and Format-Wide scans large name lists quickly. Always filter and sort before formatting, and use Out-File to save reports to disk. Well-formatted output makes scripts easier to read, share, and use in operations.

Leave a Comment

Your email address will not be published. Required fields are marked *