The Get-ChildItem cmdlet is the primary tool for listing folder contents, including files and subfolders. When working with other providers, it can also display items like registry keys or environment variables. It supports powerful filtering options for narrowing down large directory listings and emits strongly-typed .NET objects (System.IO.FileInfo and System.IO.DirectoryInfo) down the pipeline rather than plain text.
PowerShell also provides built-in aliases for this cmdlet: gci, dir, and ls. Scripts intended for sharing or long-term use should use the full cmdlet name for clarity.
Basic Usage of Get-ChildItem
Get-ChildItem -Path "C:\Reports"where -Path specifies the folder whose contents should be listed.
./list-folder-contents.ps1 Directory: C:\Reports
Mode LastWriteTime Name
---- ------------- ----
d----- 3/10/2026 9:14 AM Archive
-a---- 3/12/2026 11:02 AM Q1-Summary.csv
-a---- 3/12/2026 11:05 AM Q2-Summary.csvFiltering by Item Type: -Directory and -File
To constrain results specifically to directories or files, use the mutually exclusive dynamic switch parameters -Directory (alias -ad) and -File (alias -af).
$targetPath = "C:\inetpub\logs"
Write-Host "--- Directories in $targetPath ---" -ForegroundColor Cyan
$directories = Get-ChildItem -Path $targetPath -Directory
foreach ($dir in $directories) {
[PSCustomObject]@{
Name = $dir.Name
Mode = $dir.Mode
LastModified = $dir.LastWriteTime
}
}
Write-Host "`n--- Files in $targetPath ---" -ForegroundColor Cyan
$files = Get-ChildItem -Path $targetPath -File
foreach ($file in $files) {
[PSCustomObject]@{
Name = $file.Name
LengthKB = [math]::Round($file.Length / 1KB, 2)
Mode = $file.Mode
}
}where:
-Path $targetPath: The path to the folder being enumerated. If omitted,Get-ChildItemdefaults to the current working location.-Directory: Filters output to return onlySystem.IO.DirectoryInfocontainer objects.-File: Filters output to return onlySystem.IO.FileInfoleaf objects.$file.Length: The file size in bytes, divided by1KBusing PowerShell's built-in numeric multiplier and rounded to 2 decimal places.
./list-basic-contents.ps1--- Directories in C:\inetpub\logs ---
Name Mode LastModified
---- ---- ------------
FailedReq d---- 2026-03-15 08:30:12 AM
LogFiles d---- 2026-03-30 06:00:22 AM
--- Files in C:\inetpub\logs ---
Name LengthKB Mode
---- -------- ----
app_offline.htm 1.42 -a---
meta_config.xml 8.15 -a---Recursive Listing with -Recurse and -Depth
The -Recurse parameter lists contents of the target folder and all of its subfolders, drilling down through the entire directory tree.
Get-ChildItem -Path "C:\Reports" -Recursewhere -Recurse instructs Get-ChildItem to traverse into every subfolder, listing all nested files and folders.
Directory: C:\Reports
Mode LastWriteTime Name
---- ------------- ----
d----- 3/10/2026 9:14 AM Archive
-a---- 3/12/2026 11:02 AM Q1-Summary.csv
-a---- 3/12/2026 11:05 AM Q2-Summary.csv
Directory: C:\Reports\Archive
Mode LastWriteTime Name
---- ------------- ----
-a---- 2/01/2026 8:45 AM 2024-Q4-Summary.csvConstraining Traversal Depth
To prevent performance issues or deep stack traversals across large file systems, limit recursion boundaries using the -Depth parameter.
$baseDirectory = "C:\Application"
$items = Get-ChildItem -Path $baseDirectory -Recurse -Depth 1
foreach ($item in $items) {
[PSCustomObject]@{
RelativePath = $item.FullName.Replace($baseDirectory, "")
Type = if ($item.PSIsContainer) { "Directory" } else { "File" }
Size = if (-not $item.PSIsContainer) { $item.Length } else { $null }
}
}where:
-Recurse: InstructsGet-ChildItemto follow child subdirectories iteratively.-Depth 1: Restricts traversal to the base directory (depth 0) and its immediate subdirectories (depth 1), ignoring deeper levels.$item.PSIsContainer: Identifies whether the current item in the iteration is a directory or a file.
./list-recursive-depth.ps1RelativePath Type Size
------------ ---- ----
\bin Directory
\config Directory
\app.config File 1024
\bin\ServiceHost.exe File 154880
\bin\ServiceHost.pdb File 45056
\config\production.json File 512Filtering Results: -Filter vs. -Include and -Exclude
PowerShell provides two primary mechanisms for filtering items returned by Get-ChildItem:
- Provider-Level Filtering (
-Filter): Passes the search pattern directly to the underlying file system provider API. This is significantly faster because non-matching items are discarded before .NET objects are constructed in memory. However,-Filtersupports only a single string pattern with standard wildcards (*and?). - Engine-Level Filtering (
-Includeand-Exclude): Processed by the PowerShell engine after reading items from the provider. While slower on large volumes,-Includeand-Excludeaccept arrays of multiple search patterns.
Using -Filter
Get-ChildItem -Path "C:\Reports" -Filter "*.csv"where -Filter "*.csv" only returns items whose name matches the pattern, in this case files ending in .csv.
Directory: C:\Reports
Mode LastWriteTime Name
---- ------------- ----
-a---- 3/12/2026 11:02 AM Q1-Summary.csv
-a---- 3/12/2026 11:05 AM Q2-Summary.csvUsing -Include and -Exclude
-Include and -Exclude provide more flexible filtering options, such as supporting multiple patterns. However, they require -Recurse (or a wildcard path) to function properly, as they apply filtering after items are retrieved.
Get-ChildItem -Path "C:\Reports\*" -Include "*.csv", "*.xlsx" -Recursewhere:
-Include "*.csv", "*.xlsx"returns items matching any of the listed patterns.-Path "C:\Reports\*"where the trailing\*is required for-Include/-Excludeto correctly evaluate items inside the folder.
Directory: C:\Reports
Mode LastWriteTime Name
---- ------------- ----
-a---- 3/12/2026 11:02 AM Q1-Summary.csv
-a---- 3/12/2026 11:05 AM Q2-Summary.csv
Directory: C:\Reports\Archive
Mode LastWriteTime Name
---- ------------- ----
-a---- 2/01/2026 8:45 AM 2024-Q4-Summary.csv
-a---- 2/03/2026 9:10 AM Budget.xlsxGet-ChildItem -Path "C:\Reports\*" -Exclude "*.csv" -Recursewhere -Exclude "*.csv" returns every item except those matching the pattern.
Directory: C:\Reports\Archive
Mode LastWriteTime Name
---- ------------- ----
-a---- 2/03/2026 9:10 AM Budget.xlsxListing Hidden and System Items with -Force
By default, Get-ChildItem does not display hidden or system files. The -Force parameter reveals them, similar to dir /a in Command Prompt or ls -a in Bash.
Get-ChildItem -Path "C:\Reports" -Forcewhere -Force includes hidden and system files/folders in the results.
Directory: C:\Reports
Mode LastWriteTime Name
---- ------------- ----
d----- 3/10/2026 9:14 AM Archive
-a-h-- 3/11/2026 4:30 PM .config
-a---- 3/12/2026 11:02 AM Q1-Summary.csv
-a---- 3/12/2026 11:05 AM Q2-Summary.csvInspecting Hidden Attributes Programmatically
$repoPath = "C:\Source\Project"
$allItems = Get-ChildItem -Path $repoPath -Force
foreach ($item in $allItems) {
$attributes = $item.Attributes.ToString()
$isHidden = ($item.Attributes -band [System.IO.FileAttributes]::Hidden) -ne 0
[PSCustomObject]@{
Name = $item.Name
IsHidden = $isHidden
Attributes = $attributes
}
}where:
-Force: Overrides the default suppression of hidden and system files/directories.$item.Attributes: An enum flags property representing the low-level NTFS file attributes.-band [System.IO.FileAttributes]::Hidden: Performs a bitwise AND comparison against theHiddenattribute flag to verify whether the item is hidden.
./list-hidden-items.ps1Name IsHidden Attributes
---- -------- ----------
.git True Directory, Hidden
.gitignore False Archive
README.md False Archive
src False DirectoryPractical Usage: Auditing Storage Consumption
A common administrative task involves searching recursively for files that meet specific criteria. For example, you might need to locate all .log files larger than 10 MB or audit storage consumption across deeply nested directory trees to free up space.
The following script performs a recursive audit across a directory tree, including hidden items, and identifies the top five largest files larger than a specified threshold:
param (
[string]$AuditDirectory = "C:\DataStorage",
[int64]$MinimumSizeMB = 10
)
$thresholdBytes = $MinimumSizeMB * 1MB
Write-Host "Scanning '$AuditDirectory' for files larger than $MinimumSizeMB MB..." -ForegroundColor Cyan
$largeFiles = Get-ChildItem -LiteralPath $AuditDirectory -File -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { $_.Length -gt $thresholdBytes } |
Sort-Object -Property Length -Descending |
Select-Object -First 5
if ($largeFiles.Count -eq 0 -and $null -eq $largeFiles) {
Write-Host "No files found exceeding the $MinimumSizeMB MB threshold." -ForegroundColor Green
return
}
$largeFiles | Select-Object @(
@{ Name = "FileName"; Expression = { $_.Name } },
@{ Name = "Size(MB)"; Expression = { [math]::Round($_.Length / 1MB, 2) } },
@{ Name = "IsHidden"; Expression = { ($_.Attributes -band [System.IO.FileAttributes]::Hidden) -ne 0 } },
@{ Name = "Directory"; Expression = { $_.DirectoryName } }
) | Format-Table -AutoSizewhere:
-LiteralPath $AuditDirectory: Reads paths containing special characters (such as brackets[]) verbatim without wildcard expansion.-ErrorAction SilentlyContinue: Suppresses non-terminating permission errors on protected directories.Where-Object { $_.Length -gt $thresholdBytes }: Filters out any file smaller than the byte threshold.Sort-Object -Property Length -Descending: Sorts files in descending order by size.Select-Object -First 5: Limits results to the top 5 largest files.
./audit-large-files.ps1 -AuditDirectory "C:\DataStorage" -MinimumSizeMB 50Scanning 'C:\DataStorage' for files larger than 50 MB...
FileName Size(MB) IsHidden Directory
-------- -------- -------- ---------
database_backup.bak 512.45 False C:\DataStorage\Backups
memory_dump.dmp 256.00 True C:\DataStorage\CrashReports
virtual_disk.vmdk 180.20 False C:\DataStorage\VMs
transaction.log 95.12 False C:\DataStorage\Databases
installer_cache.msi 64.88 True C:\DataStorage\Installers