cheat sheet
dir
Display files and folders in a directory with filtering, sorting, formatting, and recursive traversal options. The Windows cmd.exe equivalent of Unix ls.
dir — List Directory Contents
What it is
dir is a built-in cmd.exe command that lists the files and subdirectories in a given path, showing name, size, date, and time by default. It has been part of DOS and Windows since their earliest versions and requires no installation. For richer output with colour, icons, and git-awareness in modern terminals, consider eza (Linux/WSL) or PowerShell's Get-ChildItem instead.
Availability
dir is built into cmd.exe on every version of Windows. It is not available in PowerShell natively — use Get-ChildItem (aliased ls, dir) there instead. Run from an elevated prompt to list protected system directories without "Access denied" on individual files.
dir /?
Output:
Displays a list of files and subdirectories in a directory.
DIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]
[/O[[:]sortorder]] [/P] [/Q] [/R] [/S] [/T[[:]timefield]] [/W] [/X] [/4]
Syntax
dir accepts an optional path or filename (wildcards supported) and a mix of switches. Without arguments it lists the current directory.
dir [drive:][path][filename] [switches]
Output: (varies — file listing or error)
Essential options
| Switch | Meaning |
|---|---|
/A | Show all files including hidden and system |
/A:H | Show only hidden files |
/A:D | Show only directories |
/A:-D | Show only files (no directories) |
/B | Bare format — names only, no header/footer |
/S | Recurse into subdirectories |
/O:N | Sort by name (A–Z) |
/O:S | Sort by size (smallest first) |
/O:D | Sort by date (oldest first) |
/O:-D | Sort by date (newest first) |
/O:-S | Sort by size (largest first) |
/P | Pause after each screenful |
/W | Wide format — 5 columns of names |
/Q | Show file owner |
/R | Show alternate data streams |
/L | Lowercase output |
/T:W | Use last-written time (default) |
/T:A | Use last-accessed time |
/T:C | Use creation time |
Basic listing
Running dir without switches shows files and subdirectories in the current directory, including a summary line with free disk space.
dir
Output:
Volume in drive C is Windows
Volume Serial Number is 1A2B-3C4D
Directory of C:\Users\alicedev\Documents
28/04/2026 10:15 <DIR> .
28/04/2026 10:15 <DIR> ..
27/04/2026 09:30 4,096 report.docx
26/04/2026 14:22 1,234 notes.txt
25/04/2026 08:00 <DIR> Archive
2 File(s) 5,330 bytes
3 Dir(s) 120,457,216,000 bytes free
rem List a specific folder
dir C:\Windows\System32
Output:
Directory of C:\Windows\System32
28/04/2026 06:00 <DIR> .
...
845 File(s) 1,234,567,890 bytes
112 Dir(s) ...
Wildcards
Wildcards * (any sequence of characters) and ? (any single character) filter the listing to matching names only.
rem All .txt files in current folder
dir *.txt
Output:
Directory of C:\Users\alicedev\Documents
26/04/2026 14:22 1,234 notes.txt
25/04/2026 11:05 890 todo.txt
2 File(s) 2,124 bytes
rem Files starting with "report"
dir report*
rem Any three-letter .log extension
dir ???.log
rem All files with any extension starting with "p"
dir *.p*
Output: (matching file listing)
Hidden and system files
By default dir omits files flagged as hidden (H) or system (S). The /A switch overrides this; qualifying attributes narrow further.
rem Show all files including hidden and system
dir /A
Output:
28/04/2026 10:15 <DIR> .
28/04/2026 10:15 <DIR> ..
27/04/2026 09:30 65,536 desktop.ini (hidden)
27/04/2026 09:30 4,096 report.docx
rem Show only hidden files
dir /A:H
rem Show only directories
dir /A:D
rem Files only (no directories)
dir /A:-D
Output: (filtered listing per attribute)
Sorting
/O controls sort order; prefix with - to reverse. Multiple sort keys can be chained (e.g. /O:EN sorts by extension then name).
rem Newest files first
dir /O:-D
Output:
Directory of C:\Users\alicedev\Documents
28/04/2026 10:15 4,096 report.docx
27/04/2026 08:00 1,234 notes.txt
26/04/2026 16:30 <DIR> Archive
rem Largest files first
dir /O:-S
rem Sort by extension, then name
dir /O:EN
rem Directories first, then by name
dir /O:GN
Output: (sorted listing)
Recursive listing
/S descends into every subdirectory, listing each directory's contents as a separate block. Combine with /B for a flat list of all paths — useful for scripting.
rem All .log files under C:\Logs, recursively
dir C:\Logs\*.log /S
Output:
Directory of C:\Logs
28/04/2026 01:00 10,240 app.log
Directory of C:\Logs\Archive
27/04/2026 01:00 8,192 app.log
26/04/2026 01:00 7,168 app.log
3 File(s) 25,600 bytes
rem Flat bare list of all paths (great for piping)
dir C:\Projects\myapp\*.py /S /B
Output:
C:\Projects\myapp\main.py
C:\Projects\myapp\utils.py
C:\Projects\myapp\tests\test_main.py
Bare format and scripting
/B suppresses the header, footer, and size column — outputting only the name (or full path with /S). This is the format to use when feeding dir output into a for loop or another command.
rem Feed a bare list into a for loop
for /f "delims=" %f in ('dir *.txt /B') do echo Processing: %f
Output:
Processing: notes.txt
Processing: todo.txt
rem Count files in a folder
dir *.* /A:-D /B | find /C /V ""
Output:
42
Alternate data streams
NTFS supports multiple data streams per file. /R reveals these hidden streams, which are used by Windows to store metadata (Zone.Identifier marks downloads from the internet).
dir downloaded.exe /R
Output:
28/04/2026 09:00 524,288 downloaded.exe
26 downloaded.exe:Zone.Identifier:$DATA
Common pitfalls
/Awith no qualifier shows everything —dir /Aincludes hidden AND system files; use/A:Hor/A:Sto narrow./Bwith/Sgives full paths, not just names — that is usually what you want for scripting, but watch for it when you only need the filename.- Wildcards in the middle of a path don't work —
dir C:\*\logsis invalid; useforloops or PowerShellGet-ChildItem -Recursefor pattern matching across directories. - Sorted output in
forloops —for /fconsumesdiroutput as plain text; the sort order you pass todiris honoured. - Free-space line at the bottom can confuse parsers — when piping
dirintofindorfindstr, watch out for the summary lines; usedir /Bto eliminate them.
Real-world recipes
Find the 10 largest files under a folder
dir C:\Users\alicedev /S /A:-D | sort /R | more
Output:
28/04/2026 ... 2,147,483,648 bigvideo.mp4
27/04/2026 ... 524,288,000 backup.zip
...
List all files modified today
for /f "tokens=1-4 delims= " %a in ('dir /B /O:-D /T:W') do @if "%a"=="28/04/2026" echo %d
Output:
report.docx
Export a full directory tree to a text file
dir C:\Projects\myapp /S /B > tree.txt
type tree.txt
Output:
C:\Projects\myapp\main.py
C:\Projects\myapp\utils.py
C:\Projects\myapp\README.md
Find files with alternate data streams (potential security indicator)
dir C:\Users\alicedev\Downloads /R | findstr ":$DATA"
Output:
26 installer.exe:Zone.Identifier:$DATA
Complete switch reference
dir accepts roughly 25 documented switches plus a few qualifiers. The essentials table above covers daily use; the full set is below.
| Switch | Meaning |
|---|---|
/A | All files including hidden and system |
/A:H | Only hidden |
/A:-H | Exclude hidden |
/A:S | Only system |
/A:-S | Exclude system |
/A:D | Only directories |
/A:-D | Only files (no directories) |
/A:R | Only read-only |
/A:A | Only files with archive bit set |
/A:L | Only reparse points (junctions, symlinks) |
/A:I | Only "not content indexed" |
/A:O | Only offline (cloud-tiered) |
/B | Bare format — names only |
/C | Show thousand separators in size column (default in some locales) |
/-C | Disable thousand separators |
/D | Wide list with dates |
/L | Lowercase all output |
/N | Long-format with names on the right (the modern default) |
/-N | Old-style listing with names on the left |
/O:N | Sort by name |
/O:E | Sort by extension |
/O:S | Sort by size (smallest first) |
/O:D | Sort by date (oldest first) |
/O:G | Group directories first |
/O:-N /O:-S /O:-D /O:-E /O:-G | Reverse the corresponding sort |
/P | Pause after each screenful |
/Q | Show file owner (NTFS) |
/R | Show alternate data streams |
/S | Recurse into subdirectories |
/T:C | Use creation timestamp |
/T:A | Use last-access timestamp |
/T:W | Use last-write timestamp (default) |
/W | Wide multi-column listing |
/X | Show 8.3 short filenames alongside long names |
/4 | Use 4-digit years (default since Windows 2000) |
The /A switch with no qualifier is equivalent to "show everything including hidden and system". Qualifiers can be combined: /A:HD (hidden directories), /A:-S-H (no system and no hidden), and /A:HSR (hidden, system, OR read-only).
Attribute filter syntax (/A:)
The /A: qualifier accepts any combination of attribute letters with optional - prefix per letter to negate. Letters are OR'd by default; the prefix - makes that letter a required-not. Order does not matter.
| Expression | Meaning |
|---|---|
/A | all files (hidden+system included) |
/A:D | only directories |
/A:-D | only non-directories (files) |
/A:H | hidden files (visible only with this filter) |
/A:-H | non-hidden |
/A:HSR | files where hidden OR system OR read-only |
/A:H-S | hidden AND not system |
/A:-H-S | not hidden AND not system (normal files) |
/A:DA | directories that also have archive bit |
rem Find every reparse point (symlink/junction) in user profile
dir /A:L /B /S C:\Users\alicedev
Output:
C:\Users\alicedev\OneDrive
C:\Users\alicedev\AppData\Local\Application Data
rem Files modified since last backup (archive bit on)
dir /A:A-D /B /S C:\Projects\myapp
Output:
C:\Projects\myapp\main.py
C:\Projects\myapp\README.md
rem Suspicious files: hidden AND system (typical malware fingerprint)
dir /A:HS /B /S C:\Users\alicedev
Output:
C:\Users\alicedev\AppData\Local\Temp\suspicious.exe
Sort order qualifiers (/O:)
/O: accepts one or more sort keys; multiple keys are applied as a stable secondary sort. Prefix any key with - to reverse direction.
| Key | Sort by |
|---|---|
N | Name (alphabetical, A→Z) |
E | Extension |
S | Size (smallest first) |
D | Date (oldest first; respects /T: choice) |
G | Group — directories first, files after |
Multi-key examples:
rem Largest files first, then alphabetical
dir /O:-SN
rem Directories first, then by extension, then alphabetical
dir /O:GEN
rem Newest first, then alphabetical
dir /O:-DN
rem By date created (not modified), oldest first
dir /T:C /O:D
Output: (sorted listing per criteria)
The combination /O:GN (groups directories first, names within) is what most users want for an ls-style listing on Linux.
Time field switch (/T:)
/T: chooses which timestamp drives both the displayed time column and the sort key when /O:D is used.
| Switch | Timestamp |
|---|---|
/T:W | Last write (default — when the file was last modified) |
/T:A | Last access (when the file was last opened) |
/T:C | Creation (when the file was first created on this filesystem) |
rem List files by creation time
dir /T:C /O:-D
Output:
27/04/2026 09:30 4,096 report.docx (created today)
25/04/2026 08:00 1,234 notes.txt
rem Last-access time (note: NTFS updates this only when atime tracking is enabled)
dir /T:A /O:-D
Output: (sorted by access time)
[!WARN] NTFS last-access time updates are disabled by default since Windows Vista to reduce write amplification on SSDs.
/T:Amay show the same timestamp as/T:Wuntil you re-enable atime tracking withfsutil behavior set disablelastaccess 0.
Long-format vs wide-format vs bare
dir has three primary output formats. Each is the right choice for a different audience.
| Format | Switch | Use case |
|---|---|---|
| Long (default) | none | Interactive — full metadata |
| Wide | /W | Quick visual scan of names only |
| Bare | /B | Script consumption — names piped into other commands |
| Display with dates | /D | Wide with date column |
rem Wide — 5 columns
dir /W
Output:
[.] [..] report.docx
notes.txt todo.txt [Archive]
rem Bare — names only, no header
dir /B
Output:
Archive
notes.txt
report.docx
todo.txt
rem Bare + recursive — full paths, ideal for scripting
dir /B /S
Output:
C:\Users\alicedev\Documents\Archive
C:\Users\alicedev\Documents\notes.txt
C:\Users\alicedev\Documents\report.docx
C:\Users\alicedev\Documents\todo.txt
C:\Users\alicedev\Documents\Archive\old.docx
For piping into for /f, findstr, or other text-processing tools, always pair /B with /A:-D (files only) to drop the directory entries.
Owner display (/Q)
/Q adds an "Owner" column showing the NTFS file owner — the security principal that owns each file. This requires a small extra round-trip to the security descriptor per file and is noticeably slower on large listings.
dir /Q
Output:
27/04/2026 09:30 MYHOST\alicedev 4,096 report.docx
26/04/2026 14:22 MYHOST\alicedev 1,234 notes.txt
25/04/2026 08:00 NT AUTHORITY\SYSTEM <DIR> Archive
Files installed by Windows Update show owner NT AUTHORITY\SYSTEM or NT SERVICE\TrustedInstaller. Files copied from another machine may show a SID rather than a name if the source user is unknown locally.
Short filenames (/X)
/X displays the legacy 8.3 (eight-dot-three) short filenames alongside long names. Modern NTFS volumes still generate short names by default for compatibility with 16-bit apps and DOS tools. They are visible only with /X.
dir /X
Output:
27/04/2026 09:30 4,096 REPORT~1.DOC report.docx
26/04/2026 14:22 1,234 NOTES.TXT notes.txt
25/04/2026 08:00 <DIR> ARCHIVE Archive
Short filenames matter when:
- Running legacy 16-bit or DOS applications that cannot handle long paths.
- Writing batch scripts that need a short, space-free filename to avoid quoting issues.
- Looking up registry entries written by installers that recorded short names.
Disabling short-name generation system-wide:
fsutil 8dot3name set 1
Output:
The registry state is now: 1 (Disable 8dot3 name creation on all volumes).
After disabling, files created later will have no short name — /X shows the long name in both columns. Existing short names remain.
Alternate data streams (/R)
NTFS files can carry multiple data streams beyond the default unnamed stream. Windows uses them for the "Zone.Identifier" mark-of-the-web on downloaded files, "summary information" on Office documents, and various custom metadata streams. /R reveals all named streams.
rem Show a freshly downloaded file with its Zone.Identifier stream
dir downloaded-installer.exe /R
Output:
28/04/2026 09:00 524,288 downloaded-installer.exe
26 downloaded-installer.exe:Zone.Identifier:$DATA
rem Read the Zone.Identifier stream content
type downloaded-installer.exe:Zone.Identifier
Output:
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://example.com/
HostUrl=https://example.com/installer.exe
ZoneId=3 means "Internet" — this is what triggers the SmartScreen prompt when you run the file.
rem Recursive: find every file in Downloads with a Zone.Identifier stream
dir C:\Users\alicedev\Downloads /R /S | findstr ":Zone.Identifier"
Output:
26 installer.exe:Zone.Identifier:$DATA
26 setup.msi:Zone.Identifier:$DATA
rem Remove the Mark of the Web from a file (clears the SmartScreen prompt)
echo. > downloaded-installer.exe:Zone.Identifier
del downloaded-installer.exe:Zone.Identifier
Output: (none — exits 0 on success)
[!WARN] Stripping the Mark of the Web disables SmartScreen's "This file came from the internet" prompt. Only do this for files you know are safe.
Recursive listing patterns
/S descends into every subdirectory. Combined with the right output format and filter, it covers most "find files in tree" tasks. Compared to where (which is purely path search) and forfiles (which can run commands per match), dir /S is the simplest enumerator.
rem All .py files under a project, bare format with full paths
dir C:\Projects\myapp\*.py /S /B
Output:
C:\Projects\myapp\main.py
C:\Projects\myapp\src\app.py
C:\Projects\myapp\tests\test_main.py
rem Same, but only files modified today (combined with attribute filter)
dir C:\Projects\myapp\*.py /S /B /A:A-D
Output: (files with archive bit set)
rem Top-level listing of every directory under root
dir C:\ /A:D /B
Output:
PerfLogs
Program Files
Program Files (x86)
ProgramData
Users
Windows
rem Find empty directories in a tree (PowerShell-assisted)
for /f "delims=" %d in ('dir C:\Projects /A:D /B /S') do (
dir "%d" /A:-D /B >nul 2>&1 || echo Empty: %d
)
Output: (paths of empty dirs)
Long paths and UNC
dir supports long-path (\\?\C:\...) and UNC (\\myhost\share\...) prefixes natively. With LongPathsEnabled set in the registry, dir also handles regular paths over 260 characters without the prefix.
rem UNC path
dir \\myhost\share
rem Extended-length prefix
dir "\\?\C:\verylongproject\src\components\NavigationDrawer\subdir\..."
rem UNC + extended-length
dir "\\?\UNC\myhost\share\verylong\..."
Output: (per path)
PowerShell equivalent: Get-ChildItem
Get-ChildItem (aliased gci, ls, and yes, dir in PowerShell) is the modern PowerShell replacement. It returns FileInfo and DirectoryInfo objects rather than printed text, which means you can pipe results into further processing without parsing.
# Equivalent of `dir`
Get-ChildItem
Output:
Directory: C:\Users\alicedev\Documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 4/26/2026 4:30 Archive
-a--- 4/27/2026 9:30 4096 report.docx
-a--- 4/26/2026 2:22 1234 notes.txt
# Hidden files included (equivalent of /A)
Get-ChildItem -Force
Output: (with hidden entries)
# Recursive (equivalent of /S)
Get-ChildItem -Recurse
Output: (full tree)
# Filter by extension (more readable than wildcards in path)
Get-ChildItem -Recurse -Include *.py -File
Output: (.py files only)
# Sort by size, descending (equivalent of /O:-S)
Get-ChildItem -File | Sort-Object Length -Descending
Output: (sorted by size)
# Sort by modified time, newest first
Get-ChildItem -Recurse -File | Sort-Object LastWriteTime -Descending
Output: (sorted by mtime)
# Filter by attribute
Get-ChildItem -Recurse -Force -Attributes Hidden
Get-ChildItem -Recurse -Force -Attributes Hidden+System
Get-ChildItem -Recurse -Attributes !Hidden+!System
Output: (per filter)
# Filter by date
Get-ChildItem -Recurse -File |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) }
Output: (files modified in the last week)
# Show owner (equivalent of /Q)
Get-ChildItem | Select-Object Name, @{N='Owner';E={(Get-Acl $_.FullName).Owner}}
Output:
Name Owner
---- -----
report.docx MYHOST\alicedev
notes.txt MYHOST\alicedev
Archive NT AUTHORITY\SYSTEM
# Alternate data streams (equivalent of /R)
Get-Item C:\Users\alicedev\Downloads\installer.exe -Stream *
Output:
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\Users\alicedev\Downloads\installer.exe::$DATA
Stream : :$DATA
Length : 524288
PSPath : ...installer.exe:Zone.Identifier
Stream : Zone.Identifier
Length : 26
# Sum total bytes in a folder
(Get-ChildItem -Recurse -File | Measure-Object Length -Sum).Sum
Output:
1234567890
# Top 10 largest files under a folder
Get-ChildItem C:\Users\alicedev -Recurse -File -ErrorAction SilentlyContinue |
Sort-Object Length -Descending |
Select-Object -First 10 FullName, @{N='SizeMB';E={[math]::Round($_.Length/1MB,2)}}
Output:
FullName SizeMB
-------- ------
C:\Users\alicedev\Videos\presentation.mp4 1024.55
C:\Users\alicedev\Downloads\big-installer.iso 512.40
C:\Users\alicedev\Documents\backup.zip 256.20
...
Get-ChildItem vs dir
| Feature | dir (cmd) | Get-ChildItem (PS) |
|---|---|---|
| Output | text | objects |
| Hidden files | /A:H or /A | -Force, -Hidden |
| Recursion | /S | -Recurse |
| Filter by attribute | /A:<flags> | -Attributes <expr> |
| Filter by name | wildcard in path | -Filter (server-side), -Include (client-side) |
| Sort | /O:<keys> | pipe to Sort-Object |
| Date filter | none built-in | Where-Object { $_.LastWriteTime ... } |
| Owner | /Q | Get-Acl per item |
| ADS | /R | Get-Item -Stream * |
| Short names | /X | not directly (use fsutil) |
| Long-path support | with prefix | native (PS 5.1+) |
| Pipelinable | no | yes |
| Locale-aware columns | yes | no (objects are locale-agnostic) |
For interactive shell use, both are fine. For any script that has to do something with the results, Get-ChildItem is strictly better because you don't have to parse dir's output.
dir vs ls vs eza
Linux's ls and the modern Rust-based eza (fork of exa) cover the same niche on Unix. dir is closer to old-school ls than to eza.
| Feature | dir | ls | eza |
|---|---|---|---|
| Default columns | varies by locale | name only | name with colour |
| Long format | default | -l | -l |
| Hidden files | /A | -a | -a |
| Human sizes | /-C thousands sep only | -h | -h (default in -l) |
| Recursion | /S | -R | -R |
| Tree view | no | no | --tree / -T |
| Colour | /A:<bg><fg> per-line | --color=auto | always-on by default |
| Icons | no | no | --icons |
| Git status | no | no | --git |
| Sort | /O:<key> | -S -t -X flags | --sort=<key> |
| Reverse | /O:-<key> | -r | -r |
| Group dirs | /O:G | --group-directories-first | default |
| Long paths | with prefix | native | native |
| Show owner | /Q | -l (default) | -l |
| Show inode | no | -i | --inode |
| Show ACL | no | -l + + | -l |
| Alternate streams | /R | n/a | n/a |
| Object pipeline | no | no | no (text) |
In WSL or Git Bash you can run ls against Windows paths via /mnt/c/... — but timezone conversion and case-sensitivity rules can surprise you. For Windows-native scripting, dir and Get-ChildItem are still the right tools.
See sections/linux/eza.md for the deep dive on the modern Rust replacement.
Output parsing in scripts
Parsing the default dir output is fragile — column widths, date format, and thousand separators vary by locale. Use /B for scripting whenever possible.
rem WRONG — depends on column layout
for /f "tokens=1-5" %a in ('dir *.txt') do echo size=%c
rem RIGHT — bare format, names only
for /f "delims=" %f in ('dir *.txt /B') do echo Processing: %f
Output:
Processing: notes.txt
Processing: readme.txt
Processing: changelog.txt
For metadata-rich loops, for /f against dir /B plus forfiles for date-and-size info is the cmd idiom:
rem Iterate files older than 7 days
forfiles /P C:\Logs /S /M *.log /D -7 /C "cmd /c echo @path"
Output:
"C:\Logs\old1.log"
"C:\Logs\old2.log"
forfiles includes the trailing comma-delimited format @path,@fsize,@fdate for more parseable output.
forfiles /P C:\Logs /S /M *.log /C "cmd /c echo @path @fsize @fdate"
Output:
"C:\Logs\app.log" 102400 4/28/2026
"C:\Logs\error.log" 4096 4/26/2026
In PowerShell, never parse — just access properties:
Get-ChildItem C:\Logs *.log -Recurse |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } |
Select-Object FullName, Length, LastWriteTime
Output:
FullName Length LastWriteTime
-------- ------ -------------
C:\Logs\old1.log 102400 4/15/2026 9:00:00 AM
Performance considerations
dir is fast on local NTFS — a typical SSD enumeration of 100,000 files in a flat directory takes about a second. On network shares it slows dramatically due to SMB round-trips per directory. Common performance traps:
/Son deep trees: each directory triggers a fresh enumeration call. For trees with thousands of folders on a network share, expect minutes./Q(owner): adds one security-descriptor lookup per file. Avoid when you don't need owners./R(alternate streams): adds one extra NTFS call per file.- Sorting (
/O:) requiresdirto load the entire result into memory before printing. Bare format without sorting (/Balone) streams output as it discovers files, which is significantly faster on huge directories.
For tree-wide enumeration in scripts, prefer robocopy /L /S /NJH /NJS /NDL /FP /NP — it uses asynchronous I/O and is 3–10× faster than dir /S /B.
rem dir /B /S — single-threaded, synchronous
dir C:\BigTree /B /S > files.txt
rem robocopy in list-only mode — much faster on large trees
robocopy C:\BigTree NUL /L /S /NJH /NJS /NDL /FP /NP /BYTES > files.txt
Output: (large file list)
Volume info and free space
The summary lines at the bottom of dir output include volume label, serial number, and free disk space.
dir
Output (last lines):
42 File(s) 1,234,567 bytes
7 Dir(s) 120,457,216,000 bytes free
To get just the free space without the listing:
rem Just the volume info header
dir /A:-D /B C:\ | find /V "" 1>nul && fsutil volume diskfree C:
Output:
Total free bytes : 120,457,216,000 (112.2 GB)
Total bytes : 511,915,388,928 (476.7 GB)
Total quota free bytes : 120,457,216,000 (112.2 GB)
For scripted disk-space checks, prefer:
Get-PSDrive C | Select-Object Used, Free
Output:
Used Free
---- ----
391458172928 120457216000
Common scenarios
List the largest 20 files in a tree
Get-ChildItem C:\BigTree -Recurse -File -ErrorAction SilentlyContinue |
Sort-Object Length -Descending |
Select-Object -First 20 FullName,
@{N='SizeMB';E={[math]::Round($_.Length/1MB,2)}}
Output:
FullName SizeMB
-------- ------
C:\BigTree\videos\demo.mp4 2048.55
C:\BigTree\archives\old.zip 512.40
Find files older than 30 days
forfiles /P C:\Logs /S /M *.log /D -30 /C "cmd /c echo @path"
Output:
"C:\Logs\2026-03\app.log"
"C:\Logs\2026-03\error.log"
Find files larger than 100 MB
Get-ChildItem C:\ -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.Length -gt 100MB } |
Select-Object FullName, @{N='SizeMB';E={[math]::Round($_.Length/1MB,2)}}
Output:
FullName SizeMB
-------- ------
C:\Users\alicedev\Downloads\big.iso 4096.00
C:\VMs\Win11.vhdx 16384.00
Count files of each type in a tree
Get-ChildItem C:\Projects\myapp -Recurse -File |
Group-Object Extension |
Sort-Object Count -Descending |
Select-Object Count, Name
Output:
Count Name
----- ----
42 .py
18 .md
12 .json
7 .yaml
3 .toml
Build a fast file inventory for indexing
rem Quick way to list every file on C: with size and date for later processing
robocopy C:\ NUL /L /S /NJH /NJS /NDL /FP /NP /BYTES /XJD > C:\inventory.txt
Output: (large file)
Detect SmartScreen-marked downloads
dir C:\Users\alicedev\Downloads /R /S /B | findstr ":Zone.Identifier"
Output:
C:\Users\alicedev\Downloads\setup.exe:Zone.Identifier
C:\Users\alicedev\Downloads\installer.msi:Zone.Identifier
Find directories sized over 1 GB
Get-ChildItem C:\Users\alicedev -Directory -ErrorAction SilentlyContinue |
ForEach-Object {
$size = (Get-ChildItem $_.FullName -Recurse -File -ErrorAction SilentlyContinue |
Measure-Object Length -Sum).Sum
[PSCustomObject]@{
Path = $_.FullName
SizeGB = [math]::Round($size/1GB, 2)
}
} |
Where-Object { $_.SizeGB -gt 1 } |
Sort-Object SizeGB -Descending
Output:
Path SizeGB
---- ------
C:\Users\alicedev\Videos 14.5
C:\Users\alicedev\Documents\Projects 3.2
Common pitfalls (extended)
- Locale-dependent output — date format, decimal separators, "File(s)" wording, and column widths all change with the system locale. Never parse
diroutput across locales; use/Bor PowerShell objects. /Sfollows reparse points by default, which can loop on circular junctions and re-list OneDrive/SharePoint placeholder folders. Use/A:-Lto exclude reparse points or switch toGet-ChildItem -Recurse -FollowSymlink:$false./Bstrips the leading dot for hidden files but only when displayed — the actual filenames still start with.. Pipe carefully.diron a UNC path without the share name (e.g.dir \\myhost) lists shares — but only if the SMB server publishes browsing. Modern shares often don't./Xshort names may not exist iffsutil 8dot3name set 1has disabled their creation, leaving the short-name column blank or duplicating the long name.- Wildcards with
/Sapply at every level —dir C:\Logs\*.log /Smatches.logfiles at every depth, not only the top level. This is usually desired but worth knowing. diroutput to a file may include BOM in some PowerShell wrappers — when redirecting from PowerShellcmd /c dir, ensure encoding.
Sources
References consulted while writing this article. Links open in a new tab.
- Microsoft Learn — dir command reference — Authoritative flag list and parameter semantics used to build the Essential options table.
- SS64 — dir — Cross-version comparison and historical syntax notes.
Tips
For any script that consumes file listings, use
dir /B /S(bare + recursive). Never parse the default columnar output across locales.
dir /A:-D /B /S | find /C /V ""counts files in a tree without spawning extra tools. Add/A:<filter>to scope by attribute.
Use
Get-ChildItemin PowerShell whenever you need to filter by date, sort by size, or iterate with logic — object-based pipelines beat text parsing every time.
forfiles /D -Nis the easiest built-in way to filter "files older than N days" without writing date arithmetic in batch.
[!WARN]
dir /Rshows alternate data streams, including Zone.Identifier on downloaded files. Don't manually strip Zone.Identifier on files you don't trust — SmartScreen relies on it.
[!WARN] Sorting (
/O:) loads the full result set into memory before printing. On directories with millions of entries, this can spike memory usage; use/Balone and pipe through external sort if needed.