es-search — Fast File Search via Everything CLI
es.exe is the CLI for Everything — a Windows
search tool that indexes the NTFS MFT and returns results instantly, regardless
of drive size or file count.
It accepts the full Everything search syntax (https://www.voidtools.com/support/everything/searching/) plus CLI-specific switches (https://www.voidtools.com/support/everything/command_line_interface/).
Availability check
Before using es.exe, verify it is reachable:
where.exe es 2>$null
If the command is not found or returns exit code 8 (Everything service not running), fall back to the standard tools (see Fallback section below).
Quick availability check pattern:
$esOutput = es -version 2>&1
if ($LASTEXITCODE -eq 8) {
# Everything service not running
} elseif ($LASTEXITCODE -ne 0 -and -not ($esOutput -match 'ES ')) {
# es.exe not installed
}
Note: es uses single-dash long flags (-version, -help, -regex).
GNU-style --version returns "Error 6: Unknown switch" — but the help text
is still printed to stderr, which can mislead automated checks. Match on the
ES prefix in stdout, not on exit code alone.
CRITICAL: argv tokenization rule
es.exe parses each argv element as a single search token. Whitespace
inside a single quoted argument is treated as a literal substring of the
filename, NOT as a token separator. This trips up almost every multi-operator
example you'd write naively.
# WRONG — one argv with spaces; es looks for literal substring "*.cpp | *.h"
es -get-result-count "*.cpp | *.h" # → 0
es -get-result-count "*.log !temp" # → 0
es -get-result-count "<*.cpp | *.h> !test" # → 0
# RIGHT (option A) — each operator/operand is its own argv
es -get-result-count "*.cpp" "|" "*.h" # → 104 631
es -get-result-count "*.log" "!temp" # → 4 270
es -get-result-count "<*.cpp" "|" "*.h>" "!test" # works
# RIGHT (option B) — single argv, NO spaces around operators
es -get-result-count "*.cpp|*.h" # → 104 631
es -get-result-count "*.log!temp" # AND-NOT, no space
es -get-result-count "<*.cpp|*.h>!test" # grouping, no spaces
Empirical rule: if you need spaces between operators (for readability) — split
into separate quoted argv elements. Otherwise glue everything inside one
quoted string. This is not a PowerShell quirk — cmd /c 'es "*.cpp | *.h"'
behaves identically.
Prefix-functions (ext:, size:, dm:, dupe:, path:, regex:) always
take ONE argv: glue the argument with : or wrap in <...>.
Quick reference
| What | Syntax | Argv form |
|---|---|---|
| Wildcard | *.log, config*.json, ?ame.txt | single |
| AND (default) | report 2024 (two argv) or *report*2024* | split / glued |
| OR | *.cpp | *.h (three argv) or *.cpp|*.h | split / glued |
| NOT | *.log !temp (two argv) or *.log!temp | split / glued |
| Grouping | <*.cpp|*.h>!test (one argv, no spaces) | glued |
| Exact phrase | "my file.txt" (escape inner quotes from PS) | single |
| Extension list | ext:cpp;h;hpp | single |
| Files only | /a-d | single |
| Folders only | /ad | single |
| Path scope | -path "C:\dir" | flag + value |
| Match against full path | -p or path:foo | flag / prefix |
| Regex | -r "pattern" (alone) or regex:pattern | flag / prefix |
| Size | size:>2gb, size:1gb..5gb, size:empty | single |
| Date modified | dm:today, dm:2024, dm:2024-01-01..2024-12-31 | single |
| Date created / accessed | dc:thisweek, da:yesterday | single |
| Attributes | attrib:H (hidden), attrib:R (readonly) | single |
| Zero-byte files | size:0 (NOT empty: — see below) | single |
| Empty folders | empty: | single |
| Duplicates by name | dupe:<expr> | single |
| Duplicates by size | sizedupe:<expr> | single |
| Limit results | -n 50 | flag |
| Offset / pagination | -o 100 -n 50 | flag |
| Count only | -get-result-count | flag |
| Sum file sizes (bytes) | -get-total-size | flag |
| Sort | -sort size-descending | flag |
| Structured output | -csv / -tsv / -efu (no JSON) | flag |
Core search patterns
Simple name / wildcard
es myfile.txt # exact name anywhere on indexed drives
es "*.log" # all .log files
es "config*.json" # name starts with "config", ends with ".json"
Boolean operators
Remember the argv rule from the top of this doc — spaces inside one quoted argv become literal substring matches, not operators. Use either separate argv tokens or glue without spaces:
# OR (three argv)
es "*.cpp" "|" "*.h"
# OR (single argv, no spaces)
es "*.cpp|*.h"
# AND-NOT (two argv)
es "*.log" "!temp"
# AND-NOT (single argv, no spaces)
es "*.log!temp"
# Grouping — easiest as single argv with no spaces
es "<*.cpp|*.h>!build"
# AND (default) — two argv equivalent to substring1 AND substring2 in name
es "README" "md" # files with both "README" and "md" in name
# Quoted exact phrase (escape inner quotes in PowerShell)
es "\`"exact phrase.txt\`""
es '"exact phrase.txt"' # easier in single-quoted PS string
Extension filter (fastest — uses the index directly)
es "ext:cpp" # all C++ source files
es "ext:cpp;h" # C++ sources AND headers (semicolon = OR on extensions)
es "ext:jpg;jpeg;png" # images
Scope to a directory
es -path "C:\Projects\MyApp" "*.cs"
es -path "D:\Logs" "ext:log"
-path restricts results to files inside the given directory tree.
For parent folder only (no recursion) use -parent "C:\dir".
Regex search
es -r "test_.*\.py" # files matching a regex (whole index)
es "regex:test_.*\.py" # same via prefix syntax
Pitfall: the CLI flag -r does NOT combine with -path or -p —
the combination returns 0 results regardless of the regex. Use the
prefix-modifier form instead:
# WRONG — silently returns 0
es -r -path "C:\src" "IFoo.*\.h"
# RIGHT — combine prefix modifiers as separate argv
es "path:C:\src" "regex:IFoo.*\.h"
Match against path, not just filename
es -p "MyApp\bin" # matches if "MyApp\bin" appears anywhere in full path
es "path:src\\tests" # same idea via syntax
Files only / directories only
es "/a-d" "*.dll" # files only (no folders)
es "/ad" "build" # directories only
es "file:*.txt" # alternative syntax
es "folder:src" # alternative syntax
Filtering by size
Size accepts bytes, KB, MB, GB, TB and comparison operators. Ranges use
... Constants are also accepted: empty, tiny, small, medium, large,
huge, gigantic.
es "size:>2gb" # everything bigger than 2 GB
es "size:>2gb" "ext:iso;vmdk" # 2 GB+ disk images (two argv — argv rule!)
es "size:100mb..1gb" # range
es "size:0" # zero-byte files
es "size:empty" # same, via constant
es -path "D:\" "size:>5gb" # large files on D:
Sorting by size (largest first)
es "size:>1gb" -sort size-descending -size
es -n 20 "ext:mp4" -sort size-descending -size -date-modified
-size, -date-modified, -dm, -dc, -da are column flags that add
columns to the output. Without them only the path is printed.
Filtering by date
Three date axes — modified (dm:), created (dc:), accessed (da:) — plus
"recently changed" (drc:). All accept the same vocabulary:
es "dm:today"
es "dm:yesterday"
es "dm:thisweek"
es "dm:lastweek"
es "dm:thismonth"
es "dm:2024" # any time in 2024
es "dm:2024-01-01..2024-12-31" # explicit range
es "dc:>2024-06-01" # created after a date
es "dm:today" "ext:cpp;