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.

cmd
dir /?

Output:

css
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.

cmd
dir [drive:][path][filename] [switches]

Output: (varies — file listing or error)

Essential options

SwitchMeaning
/AShow all files including hidden and system
/A:HShow only hidden files
/A:DShow only directories
/A:-DShow only files (no directories)
/BBare format — names only, no header/footer
/SRecurse into subdirectories
/O:NSort by name (A–Z)
/O:SSort by size (smallest first)
/O:DSort by date (oldest first)
/O:-DSort by date (newest first)
/O:-SSort by size (largest first)
/PPause after each screenful
/WWide format — 5 columns of names
/QShow file owner
/RShow alternate data streams
/LLowercase output
/T:WUse last-written time (default)
/T:AUse last-accessed time
/T:CUse creation time

Basic listing

Running dir without switches shows files and subdirectories in the current directory, including a summary line with free disk space.

cmd
dir

Output:

swift
 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
cmd
rem List a specific folder
dir C:\Windows\System32

Output:

css
 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.

cmd
rem All .txt files in current folder
dir *.txt

Output:

swift
 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
cmd
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.

cmd
rem Show all files including hidden and system
dir /A

Output:

swift
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
cmd
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).

cmd
rem Newest files first
dir /O:-D

Output:

swift
 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
cmd
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.

cmd
rem All .log files under C:\Logs, recursively
dir C:\Logs\*.log /S

Output:

c
 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
cmd
rem Flat bare list of all paths (great for piping)
dir C:\Projects\myapp\*.py /S /B

Output:

makefile
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.

cmd
rem Feed a bare list into a for loop
for /f "delims=" %f in ('dir *.txt /B') do echo Processing: %f

Output:

makefile
Processing: notes.txt
Processing: todo.txt
cmd
rem Count files in a folder
dir *.* /A:-D /B | find /C /V ""

Output:

code
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).

cmd
dir downloaded.exe /R

Output:

swift
28/04/2026  09:00           524,288 downloaded.exe
                                  26 downloaded.exe:Zone.Identifier:$DATA

Common pitfalls

  1. /A with no qualifier shows everythingdir /A includes hidden AND system files; use /A:H or /A:S to narrow.
  2. /B with /S gives full paths, not just names — that is usually what you want for scripting, but watch for it when you only need the filename.
  3. Wildcards in the middle of a path don't workdir C:\*\logs is invalid; use for loops or PowerShell Get-ChildItem -Recurse for pattern matching across directories.
  4. Sorted output in for loopsfor /f consumes dir output as plain text; the sort order you pass to dir is honoured.
  5. Free-space line at the bottom can confuse parsers — when piping dir into find or findstr, watch out for the summary lines; use dir /B to eliminate them.

Real-world recipes

Find the 10 largest files under a folder

cmd
dir C:\Users\alicedev /S /A:-D | sort /R | more

Output:

python-repl
28/04/2026  ...     2,147,483,648 bigvideo.mp4
27/04/2026  ...       524,288,000 backup.zip
...

List all files modified today

cmd
for /f "tokens=1-4 delims= " %a in ('dir /B /O:-D /T:W') do @if "%a"=="28/04/2026" echo %d

Output:

code
report.docx

Export a full directory tree to a text file

cmd
dir C:\Projects\myapp /S /B > tree.txt
type tree.txt

Output:

makefile
C:\Projects\myapp\main.py
C:\Projects\myapp\utils.py
C:\Projects\myapp\README.md

Find files with alternate data streams (potential security indicator)

cmd
dir C:\Users\alicedev\Downloads /R | findstr ":$DATA"

Output:

bash
                                  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.

SwitchMeaning
/AAll files including hidden and system
/A:HOnly hidden
/A:-HExclude hidden
/A:SOnly system
/A:-SExclude system
/A:DOnly directories
/A:-DOnly files (no directories)
/A:ROnly read-only
/A:AOnly files with archive bit set
/A:LOnly reparse points (junctions, symlinks)
/A:IOnly "not content indexed"
/A:OOnly offline (cloud-tiered)
/BBare format — names only
/CShow thousand separators in size column (default in some locales)
/-CDisable thousand separators
/DWide list with dates
/LLowercase all output
/NLong-format with names on the right (the modern default)
/-NOld-style listing with names on the left
/O:NSort by name
/O:ESort by extension
/O:SSort by size (smallest first)
/O:DSort by date (oldest first)
/O:GGroup directories first
/O:-N /O:-S /O:-D /O:-E /O:-GReverse the corresponding sort
/PPause after each screenful
/QShow file owner (NTFS)
/RShow alternate data streams
/SRecurse into subdirectories
/T:CUse creation timestamp
/T:AUse last-access timestamp
/T:WUse last-write timestamp (default)
/WWide multi-column listing
/XShow 8.3 short filenames alongside long names
/4Use 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.

ExpressionMeaning
/Aall files (hidden+system included)
/A:Donly directories
/A:-Donly non-directories (files)
/A:Hhidden files (visible only with this filter)
/A:-Hnon-hidden
/A:HSRfiles where hidden OR system OR read-only
/A:H-Shidden AND not system
/A:-H-Snot hidden AND not system (normal files)
/A:DAdirectories that also have archive bit
cmd
rem Find every reparse point (symlink/junction) in user profile
dir /A:L /B /S C:\Users\alicedev

Output:

makefile
C:\Users\alicedev\OneDrive
C:\Users\alicedev\AppData\Local\Application Data
cmd
rem Files modified since last backup (archive bit on)
dir /A:A-D /B /S C:\Projects\myapp

Output:

makefile
C:\Projects\myapp\main.py
C:\Projects\myapp\README.md
cmd
rem Suspicious files: hidden AND system (typical malware fingerprint)
dir /A:HS /B /S C:\Users\alicedev

Output:

makefile
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.

KeySort by
NName (alphabetical, A→Z)
EExtension
SSize (smallest first)
DDate (oldest first; respects /T: choice)
GGroup — directories first, files after

Multi-key examples:

cmd
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.

SwitchTimestamp
/T:WLast write (default — when the file was last modified)
/T:ALast access (when the file was last opened)
/T:CCreation (when the file was first created on this filesystem)
cmd
rem List files by creation time
dir /T:C /O:-D

Output:

swift
27/04/2026  09:30             4,096 report.docx     (created today)
25/04/2026  08:00             1,234 notes.txt
cmd
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:A may show the same timestamp as /T:W until you re-enable atime tracking with fsutil 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.

FormatSwitchUse case
Long (default)noneInteractive — full metadata
Wide/WQuick visual scan of names only
Bare/BScript consumption — names piped into other commands
Display with dates/DWide with date column
cmd
rem Wide — 5 columns
dir /W

Output:

css
[.]                    [..]                   report.docx
notes.txt              todo.txt               [Archive]
cmd
rem Bare — names only, no header
dir /B

Output:

code
Archive
notes.txt
report.docx
todo.txt
cmd
rem Bare + recursive — full paths, ideal for scripting
dir /B /S

Output:

makefile
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.

cmd
dir /Q

Output:

swift
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.

cmd
dir /X

Output:

swift
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:

cmd
fsutil 8dot3name set 1

Output:

csharp
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.

cmd
rem Show a freshly downloaded file with its Zone.Identifier stream
dir downloaded-installer.exe /R

Output:

swift
28/04/2026  09:00           524,288 downloaded-installer.exe
                                 26 downloaded-installer.exe:Zone.Identifier:$DATA
cmd
rem Read the Zone.Identifier stream content
type downloaded-installer.exe:Zone.Identifier

Output:

ini
[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.

cmd
rem Recursive: find every file in Downloads with a Zone.Identifier stream
dir C:\Users\alicedev\Downloads /R /S | findstr ":Zone.Identifier"

Output:

bash
                                 26 installer.exe:Zone.Identifier:$DATA
                                 26 setup.msi:Zone.Identifier:$DATA
cmd
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.

cmd
rem All .py files under a project, bare format with full paths
dir C:\Projects\myapp\*.py /S /B

Output:

makefile
C:\Projects\myapp\main.py
C:\Projects\myapp\src\app.py
C:\Projects\myapp\tests\test_main.py
cmd
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)

cmd
rem Top-level listing of every directory under root
dir C:\ /A:D /B

Output:

java
PerfLogs
Program Files
Program Files (x86)
ProgramData
Users
Windows
cmd
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.

cmd
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.

powershell
# Equivalent of `dir`
Get-ChildItem

Output:

lua
    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
powershell
# Hidden files included (equivalent of /A)
Get-ChildItem -Force

Output: (with hidden entries)

powershell
# Recursive (equivalent of /S)
Get-ChildItem -Recurse

Output: (full tree)

powershell
# Filter by extension (more readable than wildcards in path)
Get-ChildItem -Recurse -Include *.py -File

Output: (.py files only)

powershell
# Sort by size, descending (equivalent of /O:-S)
Get-ChildItem -File | Sort-Object Length -Descending

Output: (sorted by size)

powershell
# Sort by modified time, newest first
Get-ChildItem -Recurse -File | Sort-Object LastWriteTime -Descending

Output: (sorted by mtime)

powershell
# 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)

powershell
# Filter by date
Get-ChildItem -Recurse -File |
    Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) }

Output: (files modified in the last week)

powershell
# Show owner (equivalent of /Q)
Get-ChildItem | Select-Object Name, @{N='Owner';E={(Get-Acl $_.FullName).Owner}}

Output:

sql
Name          Owner
----          -----
report.docx   MYHOST\alicedev
notes.txt     MYHOST\alicedev
Archive       NT AUTHORITY\SYSTEM
powershell
# Alternate data streams (equivalent of /R)
Get-Item C:\Users\alicedev\Downloads\installer.exe -Stream *

Output:

yaml
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
powershell
# Sum total bytes in a folder
(Get-ChildItem -Recurse -File | Measure-Object Length -Sum).Sum

Output:

code
1234567890
powershell
# 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:

makefile
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

Featuredir (cmd)Get-ChildItem (PS)
Outputtextobjects
Hidden files/A:H or /A-Force, -Hidden
Recursion/S-Recurse
Filter by attribute/A:<flags>-Attributes <expr>
Filter by namewildcard in path-Filter (server-side), -Include (client-side)
Sort/O:<keys>pipe to Sort-Object
Date filternone built-inWhere-Object { $_.LastWriteTime ... }
Owner/QGet-Acl per item
ADS/RGet-Item -Stream *
Short names/Xnot directly (use fsutil)
Long-path supportwith prefixnative (PS 5.1+)
Pipelinablenoyes
Locale-aware columnsyesno (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.

Featuredirlseza
Default columnsvaries by localename onlyname with colour
Long formatdefault-l-l
Hidden files/A-a-a
Human sizes/-C thousands sep only-h-h (default in -l)
Recursion/S-R-R
Tree viewnono--tree / -T
Colour/A:<bg><fg> per-line--color=autoalways-on by default
Iconsnono--icons
Git statusnono--git
Sort/O:<key>-S -t -X flags--sort=<key>
Reverse/O:-<key>-r-r
Group dirs/O:G--group-directories-firstdefault
Long pathswith prefixnativenative
Show owner/Q-l (default)-l
Show inodeno-i--inode
Show ACLno-l + +-l
Alternate streams/Rn/an/a
Object pipelinenonono (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.

cmd
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:

text
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:

cmd
rem Iterate files older than 7 days
forfiles /P C:\Logs /S /M *.log /D -7 /C "cmd /c echo @path"

Output:

arduino
"C:\Logs\old1.log"
"C:\Logs\old2.log"

forfiles includes the trailing comma-delimited format @path,@fsize,@fdate for more parseable output.

cmd
forfiles /P C:\Logs /S /M *.log /C "cmd /c echo @path @fsize @fdate"

Output:

swift
"C:\Logs\app.log" 102400 4/28/2026
"C:\Logs\error.log" 4096 4/26/2026

In PowerShell, never parse — just access properties:

powershell
Get-ChildItem C:\Logs *.log -Recurse |
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } |
    Select-Object FullName, Length, LastWriteTime

Output:

lua
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:

  • /S on 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:) requires dir to load the entire result into memory before printing. Bare format without sorting (/B alone) 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.

cmd
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.

cmd
dir

Output (last lines):

scss
              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:

cmd
rem Just the volume info header
dir /A:-D /B C:\ | find /V "" 1>nul && fsutil volume diskfree C:

Output:

python
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:

powershell
Get-PSDrive C | Select-Object Used, Free

Output:

sql
        Used        Free
        ----        ----
391458172928 120457216000

Common scenarios

List the largest 20 files in a tree

powershell
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:

makefile
FullName                                  SizeMB
--------                                  ------
C:\BigTree\videos\demo.mp4               2048.55
C:\BigTree\archives\old.zip               512.40

Find files older than 30 days

cmd
forfiles /P C:\Logs /S /M *.log /D -30 /C "cmd /c echo @path"

Output:

arduino
"C:\Logs\2026-03\app.log"
"C:\Logs\2026-03\error.log"

Find files larger than 100 MB

powershell
Get-ChildItem C:\ -Recurse -File -ErrorAction SilentlyContinue |
    Where-Object { $_.Length -gt 100MB } |
    Select-Object FullName, @{N='SizeMB';E={[math]::Round($_.Length/1MB,2)}}

Output:

makefile
FullName                                  SizeMB
--------                                  ------
C:\Users\alicedev\Downloads\big.iso      4096.00
C:\VMs\Win11.vhdx                       16384.00

Count files of each type in a tree

powershell
Get-ChildItem C:\Projects\myapp -Recurse -File |
    Group-Object Extension |
    Sort-Object Count -Descending |
    Select-Object Count, Name

Output:

markdown
Count Name
----- ----
   42 .py
   18 .md
   12 .json
    7 .yaml
    3 .toml

Build a fast file inventory for indexing

cmd
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

cmd
dir C:\Users\alicedev\Downloads /R /S /B | findstr ":Zone.Identifier"

Output:

makefile
C:\Users\alicedev\Downloads\setup.exe:Zone.Identifier
C:\Users\alicedev\Downloads\installer.msi:Zone.Identifier

Find directories sized over 1 GB

powershell
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:

makefile
Path                                       SizeGB
----                                       ------
C:\Users\alicedev\Videos                     14.5
C:\Users\alicedev\Documents\Projects          3.2

Common pitfalls (extended)

  1. Locale-dependent output — date format, decimal separators, "File(s)" wording, and column widths all change with the system locale. Never parse dir output across locales; use /B or PowerShell objects.
  2. /S follows reparse points by default, which can loop on circular junctions and re-list OneDrive/SharePoint placeholder folders. Use /A:-L to exclude reparse points or switch to Get-ChildItem -Recurse -FollowSymlink:$false.
  3. /B strips the leading dot for hidden files but only when displayed — the actual filenames still start with .. Pipe carefully.
  4. dir on 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.
  5. /X short names may not exist if fsutil 8dot3name set 1 has disabled their creation, leaving the short-name column blank or duplicating the long name.
  6. Wildcards with /S apply at every leveldir C:\Logs\*.log /S matches .log files at every depth, not only the top level. This is usually desired but worth knowing.
  7. dir output to a file may include BOM in some PowerShell wrappers — when redirecting from PowerShell cmd /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-ChildItem in 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 -N is the easiest built-in way to filter "files older than N days" without writing date arithmetic in batch.

[!WARN] dir /R shows 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 /B alone and pipe through external sort if needed.