PowerShell Get-ChildItem: List Files and Folders (Full Guide)

The old dir command shows you a text listing. PowerShell Get-ChildItem does something much more useful: it returns real file and folder objects with properties like Length, LastWriteTime, Extension, and FullName that you can filter, sort, and act on immediately. Whether you’re listing all .log files over a week old, finding hidden items, or recursing an entire directory tree, this guide covers every practical Get-ChildItem pattern you need.
Basic Get-ChildItem Usage
With no arguments, Get-ChildItem lists the current directory. Pass a path to list any location:
# List current directory
Get-ChildItem
# List a specific folder
Get-ChildItem -Path 'C:\Users\Public\Documents'
# Aliases: gci, ls, dir (all call Get-ChildItem)
ls C:\Logs
dir C:\Scripts
# Show full path info
Get-ChildItem C:\Logs | Select-Object FullName, Length, LastWriteTime
Directory: C:\Logs
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 5/4/2026 9:15 AM 10240 app.log
-a--- 5/4/2026 8:01 AM 4096 error.log
d---- 5/3/2026 11:00 PM Archive
The returned objects are System.IO.FileInfo (for files) and System.IO.DirectoryInfo (for folders). Files have a Length property; folders have a GetFiles() method.
Filtering by Extension with -Filter
-Filter is the fastest way to limit results to a specific pattern — it filters at the OS level before objects are created:
# List only .log files
Get-ChildItem -Path C:\Logs -Filter '*.log'
# List only .ps1 files
Get-ChildItem -Path C:\Scripts -Filter '*.ps1'
# Filter with specific prefix
Get-ChildItem -Path C:\Logs -Filter 'app_*.log'
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 5/4/2026 9:15 AM 10240 app.log
-a--- 5/4/2026 8:01 AM 4096 app_error.log
Important limitation: -Filter only accepts a single pattern. To match multiple patterns (e.g., both .log and .txt), use -Include instead — but note that -Include requires -Recurse or a path ending in \* to work correctly.
Recursive Search with -Recurse
Add -Recurse to search all subdirectories:
# All .log files in C:\Logs and all subfolders
Get-ChildItem -Path C:\Logs -Filter '*.log' -Recurse
# Count all files recursively
(Get-ChildItem -Path C:\Scripts -Recurse -File).Count
# Combined with Where-Object for complex filtering
Get-ChildItem -Path C:\Logs -Recurse -File |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } |
Select-Object FullName, LastWriteTime
Directory: C:\Logs
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 5/4/2026 9:15 AM 10240 app.log
Directory: C:\Logs\Archive
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 4/27/2026 2:00 PM 8192 app_old.log
On deep directory trees, -Recurse can be slow. Add -Filter or -Depth N to limit scope. -Depth 2 (PS5+) limits recursion to 2 levels deep.
Including Hidden and System Files
By default, Get-ChildItem skips hidden and system files. Use -Force to include them:
# Include hidden files
Get-ChildItem -Path C:\Users\Alice -Force
# Find hidden files specifically
Get-ChildItem -Path C:\Windows -Force -File |
Where-Object { $_.Attributes -band [System.IO.FileAttributes]::Hidden }
# List all hidden folders in a directory
Get-ChildItem -Path C:\Users -Force |
Where-Object { $_.PSIsContainer -and ($_.Attributes -band 2) }
Listing Only Files or Only Folders
Use -File or -Directory to restrict the type of items returned:
# List only files (no folders)
Get-ChildItem -Path C:\Logs -File
# List only folders (no files)
Get-ChildItem -Path C:\Users\Public -Directory
# Recursive file listing only
Get-ChildItem -Path C:\Scripts -Recurse -File | Select-Object FullName
FullName
--------
C:\Scripts\backup.ps1
C:\Scripts\cleanup.ps1
C:\Scripts\Helpers\utils.ps1
-File and -Directory are cleaner than Where-Object { -not $_.PSIsContainer } and filter at the cmdlet level.
Combining with Where-Object for Advanced Filtering
Get-ChildItem combined with Where-Object handles any filtering scenario:
# Files larger than 10MB modified in the last 30 days
Get-ChildItem -Path C:\Logs -Recurse -File | Where-Object {
$_.Length -gt 10MB -and $_.LastWriteTime -gt (Get-Date).AddDays(-30)
} | Select-Object Name, @{ Name='SizeMB'; Expression={ [math]::Round($_.Length/1MB,1) } }, LastWriteTime
# Multiple extension filter (no -Filter limitation)
Get-ChildItem -Path C:\Users\Public\Documents -Recurse -File |
Where-Object { $_.Extension -in @('.docx', '.xlsx', '.pdf') } |
Sort-Object Length -Descending
Name SizeMB LastWriteTime
---- ------ -------------
system.log 15.3 5/1/2026 2:00 AM
audit.log 12.7 4/30/2026 11:59 PM
Common Errors and Fixes
-
-Filter only takes one pattern — use -Include for multiple:
Get-ChildItem -Filter '*.log','*.txt'does not work —-Filteris a single string. Use-Include @('*.log','*.txt') -Recursefor multiple patterns, or pipe toWhere-Object { $_.Extension -in @('.log','.txt') }. -
Recurse on deep trees is slow — filter early:
Get-ChildItem C:\Windows -Recursecan return hundreds of thousands of items and take minutes. Always add-Filter,-Depth, or-ErrorAction SilentlyContinueto handle access-denied folders gracefully.
Related Cmdlets / See Also
Wrapping Up
Get-ChildItem returns file objects you can immediately filter, sort, and pipeline into other commands. Use -Filter for speed on single patterns, -Include for multiple patterns, -Recurse for subdirectory traversal, and -File/-Directory to focus on one type. Your next step: try finding all .log files older than 7 days in your log folder and see what you’d be able to clean up.


