The UwView series — search with UwView, compare with UwDiff
Open and search huge files with UwView; compare two files or two folders with UwDiff. Both run on Windows, macOS and Linux. → UwDiff user manual (CLI uvd)
Command manualuvp (UwView Pro CLI)
Command manual
The uvf command manual
Covers: uvf v1.9.0 “Full Spectrum” (the CLI of the free UwView).
uvf --help lists only the essentials. This page explains the rules for writing commands, with examples. As a search tool uvf stands where ripgrep stands, so this page explains it side by side with ripgrep (the mapping is in chapter 11, performance in chapter 13).
For UwView Pro’s uvp, see the uvp command manual; for the window (GUI), see the UwView User Guide.
▶ Watch the videos: YouTube playlist “UwView|English” (how to use v1.7.3.6 “Wide Field” in 8 topics, plus an overview · Japanese · Channel @uwviewapp)
- Contents
- 1. What uvf does
- 2. The basic shape (just two forms)
- 3. Search options
- 4. Choosing files (one, several, wildcards, exclusions)
- 5. Output format
- 6. Compressed files, Word, Excel and PDF
- 7. Regular expressions (-E)
- 8. Working with the GUI (-open)
- 9. Thread count (–tune)
- 10. Exit codes
- 11. ripgrep and grep cheat sheet
- 12. Common stumbling blocks
- 13. Performance (for reference)
- v1.9.0 (Full Spectrum) results (14 October 2026, Mac; Windows and Linux checked)
- 13.1 Test environment
- 13.2 Searching compressed files (cold + hot total, seconds)
- 13.3 Cold and hot runs broken down (3G, seconds)
- 13.4 Searching several files at once (cold + hot total, seconds)
- 13.5 One large file (total of seven searches, seconds)
- 13.6 Reading the numbers
- Related
Contents
- 1. What uvf does
- 2. The basic shape (just two forms)
- 3. Search options
- 4. Choosing files (one, several, wildcards, exclusions)
- 5. Output format
- 6. Compressed files, Word, Excel and PDF
- 7. Regular expressions (-E)
- 8. Working with the GUI (-open)
- 9. Thread count (–tune)
- 10. Exit codes
- 11. ripgrep and grep cheat sheet
- 12. Common stumbling blocks
- 13. Performance (for reference)
1. What uvf does
- Searches large text files (logs, CSV, OSM XML and so on) fast
- Searches several files in one go (wildcards and subfolders too)
- When a wildcard is expanded, leaves out files matched by
.ignore/.gitignore, using the same rules as ripgrep (4.7) - Searches gz, bz2, xz, lzma, zst, lz4 and br files as they decompress (no external commands)
- Searches the text inside Word, Excel and PDF files (.docx, .docm, .xlsx, .xlsm, .pdf) as it extracts it (no index is built; 6.2)
- Opens the results in the GUI (UwView)
Building an index (.uwvz) so that later runs are fast, reading zip and pbf, tallying and replacing are features of UwView Pro’s uvp.
2. The basic shape (just two forms)
uvf <file> <term> [options] search and print the results
uvf -open [<file>] [<term>] launch the GUI (open the file if given, and search the term if given)
Examples:
uvf app.log ERROR # print the lines in app.log that contain ERROR
uvf app.log 'connection reset' # quote a term that contains spaces
uvf app.log ERROR -i # ignore case
uvf -open app.log ERROR # open it in the GUI with ERROR already searched
By default the search term is taken literally (not as a regular expression). To search with a regular expression, add -E (chapter 7).
Options can go anywhere (before or after the file and the term). Only -open must go first or last.
3. Search options
| Option | Meaning | Example |
|---|---|---|
-i |
ignore case | uvf app.log error -i |
-E |
treat the term as a regular expression (chapter 7) | uvf app.log 'code=5\d\d' -E |
-v |
print lines that do not match | uvf app.log DEBUG -v |
--json |
one JSON object per line (chapter 5) | uvf app.log ERROR --json |
-H |
always print the file name | uvf app.log ERROR -H |
-h |
never print the file name (-h on its own shows usage) |
uvf '*.log' ERROR -h |
--files |
do not search; only show what the pattern expands to (also shows how many files were excluded) | uvf '**/*.log' --files |
--no-ignore |
do not apply .ignore / .gitignore (rules added with --ignore-file still apply; 4.7) |
uvf '**/*.log' ERROR --no-ignore |
--no-ignore-files |
also drop the rules added with --ignore-file (4.7) |
uvf '**' ERROR --no-ignore --no-ignore-files |
--ignore-file <file> |
add exclusion rules; may be given more than once (4.7) | uvf '**' ERROR --ignore-file my.ignore |
--raw |
take Excel cells as stored values instead of the displayed ones (6.2) | uvf sales.xlsx 0.5 --raw |
-open |
show the results in the GUI (works with several files too; chapter 8) | uvf app.log ERROR -i -open |
Also:
| Command | Meaning |
|---|---|
uvf --help |
usage |
uvf --help files |
file selection in detail |
uvf --help regex |
regular expressions in detail |
uvf --version |
version (e.g. uvf 1.9.0 (build 26.10.13.22)) |
uvf --tune [file] [--apply] |
measure the best thread count for this machine (chapter 9) |
4. Choosing files (one, several, wildcards, exclusions)
4.1 The rule that matters most: always quote the pattern
For several files or a wildcard, put the whole thing in one pair of quotes. uvf expands it itself rather than letting the shell do it.
uvf '*.log' ERROR # ✓
uvf *.log ERROR # ✗ the shell expands it → error
uvf a.log b.log ERROR # ✗ error for the same reason
uvf 'a.log b.log' ERROR # ✓
Remember: there are only two arguments, “the files” and “the term”.
4.2 Separators
- Separate several files with spaces or commas.
- If there is even one comma, only commas separate. Use commas for paths that contain spaces (such as
Program Files). - Commas and spaces inside braces
{ }do not separate ('app.log{,.*.gz}'is one entry; 4.5).
uvf 'a.log b.log' ERROR
uvf 'logs/*.log,err/*.log' ERROR
uvf 'C:/Program Files/app/*.log,D:/logs/*.log' ERROR # commas for paths with spaces
4.3 Wildcard symbols
| Symbol | Meaning | Example |
|---|---|---|
* |
any run of characters. Does not cross the folder separator (/) |
uvf '*.log' ERROR |
? |
any single character | uvf 'app-0?.log' ERROR |
** |
any number of folders (including none) | uvf '**/*.log' ERROR |
{a,b} |
a or b (braces; since v1.9.0; rules in 4.5) | uvf '**/*.{txt,log}' ERROR |
[ ] |
not supported (taken literally) | uvf 'app[1].log' ERROR (a file named app[1].log) |
4.4 Examples
| Command | Targets |
|---|---|
uvf '*.log' ERROR |
.log files in this folder |
uvf 'logs/*.log' ERROR |
.log files directly under logs |
uvf '*/*.log' ERROR |
.log files one folder down (not the ones in this folder) |
uvf '**/*.log' ERROR |
every .log below this folder (subfolders too) |
uvf 'logs/**/*.log' ERROR |
every .log under logs |
uvf 'logs/**' ERROR |
every file under logs |
uvf '**/2026-09/*.log' ERROR |
.log files directly under any 2026-09 folder |
uvf 'app.log,app.log.*.gz' ERROR |
plain text and gz together |
uvf '**/*.{txt,log}' ERROR |
every .txt and .log below this folder |
uvf 'app.log{,.*.gz}' ERROR |
app.log and app.log.*.gz (same as 'app.log,app.log.*.gz') |
uvf 'logs/2026-{09,10}/*.log' ERROR |
.log files in logs/2026-09 and logs/2026-10 |
uvf '/var/log/app/*.log' ERROR |
absolute paths work too |
4.5 Rules
- Order: as you wrote it; within one entry, by name. Each file is searched only once.
- Hidden files and folders (names starting with
.and the like) are skipped on every OS (same as ripgrep; on Windows,.git,.gitignoreand the like used to be searched, fixed in 1.7.3.2). - Case: Linux distinguishes case; Mac and Windows do not.
- Wildcards never pick up
.uwvzfiles (UwView Pro’s index). - An entry that matches nothing is reported by name (not silently turned into zero hits).
- Braces
{a,b}(since v1.9.0): - Nesting (
{a,{b,c}}) and empty choices ({,.gz}) are allowed. - One entry expands to at most 1,000 combinations. Beyond that, uvf stops (exit code 2).
- An unclosed brace (
{a,b) or one without a comma ({},{a}) is taken literally, as part of the name. - If a file with exactly the written name exists, that file is used as is (no expansion).
- An entry that matches nothing is reported as written, braces included (nothing is reported when only some of the choices match nothing).
- The same rules apply in the file field of the window’s Command Line dialog.
- More than 1,000 files is reported (the search does not stop). The environment variable
UVF_MANY_FILESchanges the threshold. - A bare folder name (
'logs') does not work; write'logs/**'. - Symlinked folders are not followed.
- Path separators can be
/or\(Windows). - Files matched by
.ignore/.gitignoreare left out when a wildcard is expanded (4.7). This is separate from skipping hidden files.
4.6 Checking what will be searched: --files
Before searching, you can check what a pattern expands to.
$ uvf 'logs/**/*.log' --files
1 logs/app.log
2 logs/2026-09/app-0901.log
3 logs/2026-09/app-0902.log
If exclusions (4.7) left anything out, the count comes at the end (on stderr). The set of target files is the same as rg --files (the output is numbered, so it looks different; .rgignore is not read).
4.7 Exclusions (.ignore, .gitignore)
Of the files a wildcard expands to, those matched by .ignore / .gitignore are not searched (since v1.7.2.5).
The main rules are the same as ripgrep’s; comparison runs in UwTest/uv_ignore_test.sh confirm that the target list and the search results match ripgrep. The one difference is that .rgignore is not read.
If .gitignore or the like says bin/ and obj/, those are not read even with '**'. (Being tracked by git does not exclude anything; what the rules name is excluded.)
| Rule | Detail |
|---|---|
| Scope | only files expanded from a wildcard. A file you name is never excluded (uvf 'build/app.log' term searches it even if build is excluded) |
| A folder you name | a folder written at the front, as in 'build/**', is not excluded. The files inside are still checked against the rules (same as passing rg term build/ to ripgrep) |
| Files read | .ignore, .gitignore, .git/info/exclude, git’s global setting ([core] excludesFile in ~/.gitconfig, or else ~/.config/git/ignore) |
Where .gitignore applies |
only inside a git repository (some parent folder has a .git). .ignore applies outside repositories too |
| Parent folders | exclusion files above the starting folder apply too (.gitignore up to the repository root) |
| Precedence | strongest first: .ignore → .gitignore → .git/info/exclude → global setting → --ignore-file. Within one kind, a deeper folder wins |
| Excluded folders | not looked inside (so a large node_modules and the like is never read, which is fast). A file inside cannot be brought back with ! (same as git) |
| Case | case-sensitive (same as git and ripgrep; separate from the file-selection rule in 4.5) |
.rgignore |
not read (it is ripgrep’s own name; if you need it, put the same content in .ignore) |
Syntax (same as .gitignore):
| Pattern | Meaning |
|---|---|
blank lines, lines starting with # |
ignored (\# for a literal #) |
*.log |
matches .log at any depth |
/build |
only directly under the folder holding that exclusion file (anchored by the leading /) |
doc/*.md |
with a / in the middle, the path is relative to that exclusion file’s folder |
build/ |
matches folders only |
* ? [a-z] [!a-z] |
wildcards (* and ? do not cross /). [ ] works in exclusion patterns (but not in file selection, 4.3) |
**/tmp, out/**, a/**/b |
any depth |
!keep.log |
cancels an exclusion. Later lines win |
| trailing spaces | ignored (\ for a literal space) |
Exclusion files with CRLF line endings (Windows) or a leading BOM are read too.
Options:
| Option | Meaning | Example |
|---|---|---|
--no-ignore |
skip exclusions from .ignore, .gitignore, .git/info/exclude and the global setting. Rules added with --ignore-file still apply (same as ripgrep 15) |
uvf '**' ERROR --no-ignore |
--no-ignore-files |
also drop rules added with --ignore-file (same name as ripgrep) |
uvf '**' ERROR --no-ignore --no-ignore-files |
--ignore-file <file> |
add exclusion rules; may repeat. Weakest of all, so it loses to a ! in .ignore and the like. A name-only rule (*.md and the like) matches anywhere, wherever the file sits |
uvf '**' ERROR --ignore-file extra.ignore |
--files |
show what will be searched (with the count of excluded files at the end) | uvf '**' --files |
How you are told:
- Nothing is added to search results (excluded files are left out silently, as in grep and ripgrep).
--filesends with “excluded N files, M folders (not looked inside)”. To see what was left out, compare with the list produced with--no-ignore.- When exclusions leave a pattern with no files at all, it says “no files match:
(excluded by .gitignore etc.; –no-ignore includes them)”. It does not silently return zero hits. - When
--ignore-fileadded rules, the notice also says “rules added with –ignore-file are turned off with –no-ignore-files” (because--no-ignorealone does not turn them off).
Example (a repository whose .gitignore says build/, *.tmp and !keep.tmp, and whose logs/.ignore says old/):
$ uvf '**' --files
1 app.log
2 keep.tmp
3 logs/b.log
uvf: excluded 1 file, 2 folders (not looked inside) (.gitignore etc.; --no-ignore includes them)
$ uvf 'build/**' --files # a folder you name is not excluded
1 build/a.log
$ uvf 'x.tmp' --files # nor is a file you name
1 x.tmp
uvf '**/*.log' ERROR --no-ignore # search without exclusions
uvf '**' ERROR --ignore-file ~/extra.ignore # search with extra rules
4.8 Awkward names
| Name | How to write it | Example |
|---|---|---|
| One file with spaces | write it as is (if the whole string is an existing file, it is taken as one file; since 1.7.2.7) | uvf 'sp dir/my log.txt' ERROR |
| One wildcard with spaces | add a trailing comma (with a comma present, spaces do not separate) | uvf 'C:/Program Files/app/*.log,' ERROR |
| Several entries with spaces | separate with commas | uvf 'C:/Program Files/app/*.log,D:/logs/*.log' ERROR |
| A name containing a comma | a comma is a separator, so replace it with ?. ? matches any character, so a-b.log or aXb.log would also match. Check with --files first |
uvf 'a?b.log' --files, then uvf 'a?b.log' ERROR |
A name starting with - |
prefix ./ |
uvf ./-debug.log ERROR |
A name with [ ] |
write it as is (not a wildcard) | uvf 'app[1].log' ERROR |
A name with { } |
{} and {a} (no comma) can be written as is. {a,b} with a comma expands as braces, but if a file with exactly that name exists, that file is used (4.5). Check with --files first |
uvf 'report{1}.log' ERROR |
5. Output format
| Command | Format |
|---|---|
uvf app.log ERROR (one file) |
line<TAB>text |
uvf '*.log' ERROR (several files) |
file:line<TAB>text |
uvf app.log ERROR -H |
file:line<TAB>text even for one file |
uvf '*.log' ERROR -h |
line<TAB>text even for several files |
uvf app.log ERROR --json |
one JSON object per line: {"n":line,"line":"text"} |
uvf '*.log' ERROR --json |
for several files, {"file":"a.log","n":…,"line":"…"} |
$ uvf app.log ERROR
128 2026-09-27 10:01:02 ERROR connection reset
512 2026-09-27 10:05:44 ERROR timeout
$ uvf '*.log' ERROR
a.log:128 2026-09-27 10:01:02 ERROR connection reset
b.log:7 2026-09-27 11:00:00 ERROR disk full
- Line numbers start at 1.
- With CRLF line endings (Windows), only the text is printed.
- ripgrep prints
file:line:text; uvf puts a TAB after the line number.cut -f2-extracts just the text.
6. Compressed files, Word, Excel and PDF
Compressed files are searched as they decompress. No external commands (gzip, xz and so on) are used.
| Format (extension) | Command | uvf |
|---|---|---|
.gz |
uvf app.log.gz ERROR |
searched (alone or mixed with others) |
.bz2 .xz .lzma .zst .lz4 .br |
uvf app.log.xz ERROR |
searched |
.docx .docm .xlsx .xlsm .pdf |
uvf report.docx Tokyo |
the text is extracted and searched (since v1.9.0; 6.2) |
.doc .xls |
uvf old.doc Tokyo |
not supported (old formats; save them as .docx / .xlsx in Word / Excel) |
.zip |
uvf logs.zip ERROR |
not supported (unpack it first; uvp handles zip) |
.pbf (OSM) |
uvf japan.osm.pbf 東京 |
not supported (uvp converts it to XML) |
.tar.gz |
uvf logs.tar.gz ERROR |
not supported (a tar bundles several files; unpack it first) |
.uwvz |
uvf app.log.uwvz ERROR |
not supported (UwView Pro’s index) |
| anything else | uvf app.log ERROR |
treated as text |
- The format is recognised by the extension. If a
.gzfile does not actually contain gzip data, you are told so. - Plain and compressed files can be searched together in one run:
uvf 'app.log,app.log.*.gz' ERROR - An xz file made of several blocks (the default from xz 5.6) is decompressed with several threads.
6.1 Character encoding
The encoding is detected from the start of the file (up to 256 KB). There is no option to set it.
| Order | Test | Encoding |
|---|---|---|
| 1 | a BOM at the start | UTF-8, UTF-16LE, UTF-16BE, UTF-32LE |
| 2 | no BOM, valid UTF-8 (including pure ASCII) | UTF-8 |
| 3 | otherwise, compare Shift_JIS and EUC-JP; the one with fewer odd bytes wins | Shift_JIS or EUC-JP |
| 4 | undecided | Shift_JIS |
UTF-16 / UTF-32 without a BOM, UTF-32BE and other encodings (Latin-1, GBK, ISO-2022-JP …) are not detected.
6.2 Word, Excel and PDF (since v1.9.0)
uvf extracts the text of Word, Excel and PDF files as it searches. No index is built (nothing is created next to the original). One file or a pattern such as 'docs/**/*.pdf' both work.
uvf report.docx Tokyo # Word
uvf 'expenses/**/*.xlsx' taxi # Excel (several files)
uvf 'docs/**/*.pdf' contract -i # PDF
uvf sales.xlsx 0.5 --raw # Excel, by the stored value instead of the displayed one
| Format | Extensions | What one line looks like |
|---|---|---|
| Word | .docx .docm |
one line per paragraph. A table row is one line, with the cells separated by tabs. Footnotes and comments follow at the end, with a prefix |
| Excel | .xlsx .xlsm |
sheet!row<TAB>column A<TAB>column B…. Cells hold the displayed value (such as 50%); with --raw, the stored value (0.5; a formula gives its result as a number) |
.pdf |
a ## page N line for each page, followed by that page’s lines in reading order (on two-column pages, the left column first) |
The line number in the output is the line number in the extracted text (e.g. 2<TAB>Sales!2<TAB>apples<TAB>50%).
- Refused: old formats (
.doc,.xls), password-protected files, PDFs with no text (images only; there is no OCR) and damaged files. uvf says why and exits with code 2. Inside a pattern for several files, such a file is named and skipped, and the rest are searched (the exit code is 2 if anything was skipped). - Cannot be written back in the original format (the extracted text can be saved or copied in the window).
- Opened in the window (
-open), the file shows a progress bar while its text is extracted to a temporary folder, and then that text opens. - The component that reads Word, Excel and PDF (PdfPig, Apache 2.0) makes the uvf command larger (about 6.7 MB → 17.4 MB).
7. Regular expressions (-E)
With -E, the search term is treated as a regular expression. UwView uses .NET regular expressions. The common syntax is the same as ripgrep (Rust), but some differences change what matches (7.2).
7.1 Common syntax
| Syntax | Meaning | Example |
|---|---|---|
. |
any single character | uvf app.log 'E.ROR' -E |
* + ? {2,5} |
0 or more, 1 or more, 0 or 1, 2 to 5 times | uvf app.log 'code=\d{3}' -E |
[abc] [^abc] [0-9] |
character class | uvf app.log 'code=[45][0-9][0-9]' -E |
( ) a|b |
group, alternation | uvf app.log '(ERROR|WARN) disk' -E |
^ $ |
line start, line end | uvf app.log '^2026-09-27' -E |
\d \w \s \b |
digit, word character (Japanese too), whitespace, word boundary | uvf app.log '\bERROR\b' -E |
(?i) |
ignore case (same as -i) |
uvf app.log '(?i)error' -E |
uvf app.log 'ERROR|WARN' -E
uvf access.log '" (4|5)\d\d ' -E
uvf app.log '^2026-09-27 1[0-2]:' -E
7.2 Differences from ripgrep
| Syntax | uvf (.NET) | ripgrep |
|---|---|---|
| Default | uvf app.log 'a.b' (literal “a.b”; regex needs -E) |
rg 'a.b' app.log (regex; literal needs -F) |
| Lookahead / lookbehind | uvf app.log 'ERROR(?=.*disk)' -E (supported) |
rg -P 'ERROR(?=.*disk)' app.log (with PCRE2: -P or --engine auto) |
| Backreferences | uvf app.log '(\w+) \1' -E (supported) |
rg -P '(\w+) \1' app.log (with PCRE2: -P or --engine auto) |
| Named groups | uvf app.log '(?P<code>\d{3})' -E (uvf rewrites it as (?<code>…); the standard .NET form is (?<code>\d{3})) |
rg '(?P<code>\d{3})' app.log |
| POSIX classes | uvf app.log '[A-Za-z]+' -E ([[:alpha:]] is not supported; the error suggests the equivalent range) |
rg '[[:alpha:]]+' app.log (matches ASCII letters only) |
| Digits, whitespace | uvf app.log '[0-9]+' -E (\d also matches full-width digits) |
rg '\d+' app.log (Unicode digits) |
| Scripts (Han, Hiragana) | uvf app.log '\p{IsCJKUnifiedIdeographs}+' -E (\p{Han} is not supported; the range differs slightly) |
rg '\p{Han}+' app.log |
Rewrite examples (1): POSIX classes → the same range as ripgrep (the lines matched do not change):
| ripgrep | uvf | Note |
|---|---|---|
rg '[[:alpha:]]+' app.log |
uvf app.log '[A-Za-z]+' -E |
\p{L} would also match Japanese and more (wider) |
rg 'id=[[:digit:]]+' app.log |
uvf app.log 'id=[0-9]+' -E |
\d would also match full-width digits (12) |
rg 'a[[:space:]]b' app.log |
uvf app.log 'a[ \t\r\n\f\v]b' -E |
\s would also match full-width spaces and more |
Rewrite examples (2): Unicode scripts → a close range, with different matches (.NET has no script property, so a nearby range is written with Unicode blocks; the matched characters are not identical):
| ripgrep | uvf (close equivalent) | Difference |
|---|---|---|
rg '\p{Han}+' app.log |
uvf app.log '[\p{IsCJKUnifiedIdeographs}\p{IsCJKUnifiedIdeographsExtensionA}\p{IsCJKCompatibilityIdeographs}々〇]+' -E |
\p{IsCJKUnifiedIdeographs} alone misses 々, 〇 and Extension A (㐀 etc.). Kanji in Extension B and later cannot be included with block names (.NET regular expressions match one UTF-16 unit at a time) |
rg '\p{Hiragana}+' app.log |
uvf app.log '\p{IsHiragana}+' -E |
block versus script gives a slightly different range (combining voiced marks and the like) |
rg '\p{Katakana}+' app.log |
uvf app.log '[\p{IsKatakana}ヲ-゚]+' -E |
\p{IsKatakana} alone misses half-width kana. The long-vowel mark ー is in the block but counted as Common in the script |
To include Japanese and full-width characters, use \p{L} (letters), \d (digits) and \s (whitespace). They cover a wider range than ripgrep’s [[:alpha:]] and the like.
7.3 Rules
- Matching is line by line (no multi-line matches).
- A single match attempt that runs over 5 seconds is stopped. Rethink the expression.
- A mistake in the expression is reported as “Invalid regular expression” before the search starts.
- Matching is done on characters, regardless of the file’s encoding.
8. Working with the GUI (-open)
| Form | What happens |
|---|---|
uvf -open |
just launches the GUI (UwView) |
uvf -open app.log |
opens app.log in the GUI |
uvf -open app.log ERROR |
opens it with ERROR already searched |
uvf app.log ERROR -i -E -open |
shows a search with -i -E -v in the GUI |
uvf -open '*.log' ERROR |
shows multi-file results in the GUI (8.1) |
uvf '*.log' ERROR -i -open |
the same (-open at the end works too; -i -E -v apply) |
uvf -open '*.log' |
opens without searching (shows only file number 1 and the file list) |
-opengoes first or last. It cannot be combined with--json.
8.1 Viewing multi-file results in the GUI
With uvf -open '*.log' ERROR, uvf searches first and hands the results to the GUI (the GUI does not search again).
- Right after opening, file number 1 is shown in the main tab (the first tab).
- The line-number column of the results window reads
file number:line(e.g.3:128). The numbers are the same as in--files. - Selecting a row shows the real file name on the line at the bottom of the window (selecting alone does not open the file).
- Double-click (or Enter) shows that file in the main tab and jumps to that line (the line is centred and highlighted).
- If the file is already in the main tab, it just jumps.
- If the file is open in an extra tab, it switches to that tab and jumps (the same file is never opened twice).
- If it is not open anywhere, the main tab’s content is replaced with that file (the previous file is closed).
- A compressed file (gz, bz2 and the rest) is decompressed next to the original, then opened at the matching line (no confirmation dialog; if a decompressed copy newer than the original already exists, it is used).
- A Word, Excel or PDF file has its text extracted to a temporary folder first, then opens (progress is shown; nothing is created next to the original).
- If a file has changed since the search, it still opens, and the status bar says “This file has changed since the search”. If the file is gone, it says “File not found”.
- The number of hits handed to the window is capped by the “Maximum hits kept per search” setting. Even with no limit set, it stops at 1,000,000 and the window shows “Stopped at the limit” (because the text is handed over too).
8.2 File list and tabs
The “File list” button in the main window (a bulleted-list icon; the results window has the same button) opens a table mapping numbers to real files.
Buttons are icons; the name appears when you hover (since 1.7.3; Yes/No, Open/Close, Save and Cancel stay as text).
| Column | Content |
|---|---|
| Number | the same number as --files |
| File | the name as you wrote it (hover for the absolute path) |
| Hits | the number of hits in that file |
| Size | the file’s size |
| Far right | “Main” if it is in the main tab, “Tab” if it is open in an extra tab |
- Double-click (or Enter) a row to open it.
- “Open in tab” at the top right switches how it opens (remembered next time).
- Off (default): the main tab’s content is replaced with that file, shown from the start.
- On: opens that file in an extra tab. Tabs are numbered, like
2:app-0902.log. - Up to 8 tabs (1 main + 7 extra). With 8 open, it does not open another and says “Up to 8 tabs” (it never closes an old tab for you). Only tabs opened from this list count.
- A file that is already open just switches to its tab.
- The main tab cannot be closed (it has no close button). Extra tabs close like any other tab.
- However many tabs there are, they stay on one row and scroll sideways (the mouse wheel works too). Names longer than 27 characters end in
...; hover to see the full name. - The main tab is grey, so you can tell it from extra tabs (since 1.7.3.4).
- The window title reads
UwView(uvf)-Full Spectrum(v1.9.0), so you can see the version. - zip and pbf files only get a number (they are not searched and cannot be opened).
8.3 uvf versus uvp (multi-file GUI)
| Item | uvf | uvp |
|---|---|---|
| From a result to its source line | reopens the file first, then jumps (a large file takes a moment) | jumps within the bundled text right away |
| Second search | reads everything again | fast, thanks to the index |
| GUI search box | searches only the one file in the main tab (search several files again from the CLI) | searches the whole bundle |
| Narrowing, tallying | no | yes |
| zip, pbf | no | yes |
| Word, Excel, PDF | extracted while searching (no index) | an index next to the file (report.docx.uwvz) |
9. Thread count (–tune)
Measures on this machine how many threads to use for searching.
uvf --tune # measure and show the recommended value
uvf --tune big.log # measure with a large file of your own
uvf --tune --apply # save the measured value to the settings (used by uvf; no effect on search in the free edition's window)
The default is usually fine. It helps on machines with many CPU cores or with slow disks.
10. Exit codes
| Code | Meaning |
|---|---|
| 0 | found |
| 1 | not found |
| 2 | error (missing file, bad regular expression, bad pattern, etc.) |
Word, Excel and PDF files that are refused (.doc, .xls, password-protected, PDFs with no text, damaged) also give 2 (6.2). So does a brace pattern with more than 1,000 combinations (4.5).
The same as grep and ripgrep, so it works as is in shell scripts.
if uvf app.log 'FATAL' > /dev/null; then echo "FATAL found"; fi
11. ripgrep and grep cheat sheet
The examples use the file app.log, the folder logs and the term ERROR.
| What you want | ripgrep | uvf |
|---|---|---|
| Literal search | rg -F ERROR app.log |
uvf app.log ERROR |
| Regex search | rg 'ERROR|WARN' app.log |
uvf app.log 'ERROR|WARN' -E |
| Ignore case | rg -F -i error app.log |
uvf app.log error -i |
| Non-matching lines | rg -F -v DEBUG app.log |
uvf app.log DEBUG -v |
| Subfolders too | rg -F ERROR logs/ |
uvf 'logs/**' ERROR |
| One extension only | rg -F -g '*.log' ERROR |
uvf '**/*.log' ERROR |
| Compressed files too | rg -z -F ERROR app.log.gz |
uvf app.log.gz ERROR (no -z needed) |
| Always print the file name | rg -F -H ERROR app.log |
uvf app.log ERROR -H |
| Never print the file name | rg -F -I ERROR logs/ |
uvf 'logs/**' ERROR -h |
| List the target files | rg --files logs/ |
uvf 'logs/**' --files (same exclusion rules; .rgignore is not read) |
Honour .ignore / .gitignore |
rg -F ERROR . (the default) |
uvf '**' ERROR (the default; 4.7) |
| Do not exclude | rg -F --no-ignore ERROR . |
uvf '**' ERROR --no-ignore |
| Add exclusion rules | rg -F --ignore-file extra.ignore ERROR . |
uvf '**' ERROR --ignore-file extra.ignore |
| Drop the added rules too | rg -F --no-ignore --no-ignore-files ERROR . |
uvf '**' ERROR --no-ignore --no-ignore-files |
| JSON output | rg -F --json ERROR app.log |
uvf app.log ERROR --json (different shape) |
grep’s -h (no file names) and ripgrep’s -h (help) mean opposite things. uvf follows grep (“no file names”) and shows usage only when -h is given on its own.
What it is good at: uvf suits searching large files and compressed logs quickly while honouring exclusions, then checking the results in the GUI.
For fine control over search conditions and output (surrounding lines, counts only, matched parts only, standard input and so on), ripgrep offers more (11.1).
11.1 What ripgrep has and uvf does not
The table in chapter 3 is every option uvf has. The ripgrep features below are not in uvf; where there is a workaround, it is in the right-hand column.
| ripgrep | What it does | In uvf |
|---|---|---|
rg -F -C 3 ERROR app.log (and -A -B) |
surrounding lines too | none (UwView Pro: uvp app.log ERROR -C 3) |
rg -F -w ERROR app.log |
whole-word match | uvf app.log '\bERROR\b' -E |
rg -F -x ERROR app.log |
whole-line match | uvf app.log '^ERROR$' -E |
rg -F -c ERROR app.log |
count of matching lines | uvf app.log ERROR | wc -l (the count is also printed at the end as “N hits”) |
rg -F -l ERROR logs/ |
names of matching files only | uvf 'logs/**' ERROR --json | jq -r .file | uniq (needs jq). If no path contains a colon, uvf 'logs/**' ERROR | cut -d: -f1 | uniq also works (a shortcut that fails with Windows paths like C:) |
rg -F -q ERROR app.log |
just whether it exists (stop at the first) | uvf app.log ERROR > /dev/null (check the exit code; it reads to the end even after a hit) |
rg -F -m 5 ERROR logs/ |
per-file hit limit | none (for the first N overall, uvf 'logs/**' ERROR | head -5) |
rg -o 'code=\d+' app.log |
print only the matched part | none (to count by value, uvp’s -uniq) |
rg -e ERROR -e WARN app.log (and -f) |
several terms | uvf app.log 'ERROR|WARN' -E (no pattern file -f) |
cat app.log | rg ERROR |
search standard input | none (write it to a file first) |
rg -U 'a\nb' app.log |
multi-line matches | none (matching is line by line) |
rg --hidden ERROR |
include hidden files | none (a hidden file can still be searched by naming it) |
rg -L ERROR |
follow symlinked folders | none |
rg -t log ERROR, --max-depth, --max-filesize |
filter by type, depth, size | type and depth through the pattern (uvf '**/*.log' ERROR, uvf '*/*.log' ERROR); no size filter |
rg -E sjis ERROR app.log |
set the encoding | none (detected automatically) |
rg -r 'WARN' ERROR app.log |
print with replacements | none (UwView Pro: uvp app.log ERROR -replace WARN) |
rg -0, --column, -b |
NUL separators, column number, byte offset | none |
Also, files are given as a single string (chapter 4). Names containing spaces, commas, [ ] or { } may not work as is,
and for existing scripts that pass file names one by one, ripgrep is the better fit.
12. Common stumbling blocks
| Symptom | Cause and fix |
|---|---|
| “Several files were passed directly” | You forgot the quotes, so the shell expanded the wildcard. Quote it: uvf '*.log' term |
| A path with spaces matches nothing | It is being split at the spaces. Separate with commas |
*/*.log misses deeper subfolders |
* covers one level only. To go all the way down, use '**/*.log' |
[[:alpha:]] gives an error |
Not supported in .NET regular expressions. Rewrite it as \p{L} (7.2) |
| A regex does not match | You forgot -E (the default is a literal search) |
| Cannot search a zip | uvf does not handle zip. Unpack it or use uvp |
| A Word, Excel or PDF file is refused with exit 2 | Old formats (.doc, .xls), password-protected files, PDFs with no text (images only; there is no OCR) and damaged files are refused. Save a .doc / .xls as .docx / .xlsx in Word / Excel (6.2) |
| Hidden files are not searched | By design (4.5) |
| A file you expect is missing | It may be excluded by .gitignore / .ignore. Check the “excluded N files” line at the end of --files, and use --no-ignore to include it (4.7) |
.gitignore works in a git folder but not elsewhere |
By design. .gitignore applies only inside a git repository. To apply rules anywhere, put them in .ignore |
13. Performance (for reference)
v1.9.0 (Full Spectrum) results (14 October 2026, Mac; Windows and Linux checked)
The latest results, measured with v1.9.0 on a Mac (14 October 2026; Apple M4, 32 GB, external USB SSD). Ratios are ripgrep’s (or the other tool’s) time ÷ uvf / uvp‘s time (total of cold + hot); under 1.5× counts as on par.
The same test suite was also run on Windows and Linux to confirm that everything works correctly (correctness tests: 66 input-type checks, 34–36 multi-file checks and 43 exclusion checks all passed, and the speed runs had zero mismatches against ripgrep). Windows and Linux speeds are shown in the two right-hand columns for reference only, since the machines and conditions differ from the Mac.
| ripgrep ÷ uvf / uvp (total of cold + hot) | Mac | Windows (reference) | Linux (reference) |
|---|---|---|---|
| One 3 GB file, overall (30–32 items) | 2.56 | 2.24 | 1.50 |
| One 10 GB file, overall (30 items) | 2.51 | 3.17 | 1.96 |
Free uvf, seven searches (3 GB / 10 GB) |
1.08 / 1.08 (on par) | 1.46 / 1.92 | 1.32 / 1.06 |
uvp, seven searches (3 GB / 10 GB, incl. building the index) |
3.44 / 3.55 | 2.48 / 2.48 | 1.42 / 2.06 |
uvp, tally and sort (3 GB and 10 GB) |
4.2–4.9 | 2.0–3.6 | 1.4–3.3 |
uvp, Shift-JIS / EUC-JP / UTF-16 (3–6 GB, from the 2nd run) |
5.4–38.8 | 2.2–14.1 | 2.0–15.3 |
uvp, three log examples (Linux kernel, 60,000 files) |
2.35–4.56 | 1.26–2.48 | 1/2.85–1/3.21 |
| Output check | 0 mismatches | 0 mismatches | 0 mismatches |
The first run (including building the index) is about 1/1.4–1/1.7 of ripgrep for Shift-JIS and EUC-JP (the range over three runs on a Mac). Fast-to-decompress lz4 including the first run is 1/1.4. In the reference Windows and Linux runs, uvp‘s first run, zst, lz4 and first-time bundling of many files showed losses beyond 1.5×.
Details: the v1.9.0 “Full Spectrum” article.
Unless noted, the numbers below in this chapter were measured with earlier versions.
These are examples measured on one Mac. Disk, CPU and data all change the result.
The ratio is “ripgrep’s time ÷ uvf’s time”. Above 1 means uvf is faster (🟢); below 1 (written 1/x) means ripgrep is faster (🍊). Read a gap under 1.5× as “on par” (under 1.3× for totals of seven or more items).
13.1 Test environment
| Item | Value |
|---|---|
| Machine | Mac (Apple M4, 10 cores, 32 GB RAM), external USB SSD |
| Version | uvf 1.7.3.6, compared with ripgrep 15.2.0 |
| Threads | 8 (the default) |
| Data | OSM (Japan) XML. 1G = 979 MB, 3G = 2,938 MB (the 1G content joined three times), 10G = 10,255 MB, 50G = 51,255 MB. The search term is 東京 (Tokyo) |
| Method | Each time: sync → drop caches (purge) → wait 10 s → 1st run (cold) → 2nd run (hot) straight after. Time is from command start to finish |
| Checks | In every measurement, the results were checked against ripgrep (or a combination such as sed, sort and uniq) — zero mismatches |
| Raw records | UwTest/mac_result/20260929-095527-cspeed (3G in 13.2, and 13.3) and UwTest/mac_result/20260929-030006-suite (1G in 13.2, 13.4 and 13.5), both 2026-09-29 |
13.2 Searching compressed files (cold + hot total, seconds)
ripgrep runs rg -z -n -F 東京 file (using external decompressors); uvf runs uvf file 東京. One regular measurement each.
| Format | 1G: size | rg -z | uvf | Ratio | 3G: size | rg -z | uvf | Ratio |
|---|---|---|---|---|---|---|---|---|
| Plain (baseline, rg) | 979 MB | 1.34 | 1.24 | 1.08 🟢 | 2,938 MB | 3.67 | 3.54 | 1.04 🟢 |
| gz | 106 MB | 0.94 | 0.78 | 1.21 🟢 | 318 MB | 2.66 | 2.07 | 1.29 🟢 |
| bz2 | 84 MB | 16.30 | 15.59 | 1.05 🟢 | 251 MB | 47.26 | 45.53 | 1.04 🟢 |
| xz | 84 MB | 1.34 | 1.46 | 1/1.09 🍊 | 253 MB | 3.53 | 3.81 | 1/1.08 🍊 |
| lzma | 85 MB | 7.04 | 5.74 | 1.23 🟢 | 254 MB | 20.80 | 16.99 | 1.22 🟢 |
| zst | 116 MB | 1.15 | 1.07 | 1.07 🟢 | 348 MB | 3.26 | 3.04 | 1.07 🟢 |
| lz4 | 178 MB | 0.72 | 0.64 | 1.12 🟢 | 533 MB | 1.87 | 1.70 | 1.10 🟢 |
| br | 97 MB | 1.77 | 1.45 | 1.22 🟢 | 292 MB | 5.05 | 4.13 | 1.22 🟢 |
| Mixed (4 plain + gz, xz, zst, bz2) | 538 MB | 2.39 | 2.29 | 1.04 🟢 | 1,615 MB | 6.63 | 6.47 | 1.02 🟢 |
| Mixed (gz, xz, zst, bz2) | 97 MB | 4.37 | 4.17 | 1.05 🟢 | 292 MB | 13.31 | 12.13 | 1.10 🟢 |
13.3 Cold and hot runs broken down (3G, seconds)
| Format | Tool | 1st run (cold) | 2nd run (hot) |
|---|---|---|---|
| Plain | rg | 3.34 | 0.33 |
| Plain | uvf | 3.10 | 0.44 |
| xz | rg -z | 1.79 | 1.74 |
| xz | uvf | 1.92 | 1.89 |
| gz | rg -z | 1.35 | 1.31 |
| gz | uvf | 1.04 | 1.03 |
On the second run a plain file is already in memory, so neither tool reads the disk. A compressed file is decompressed again on every run, so the second run takes about as long as the first.
13.4 Searching several files at once (cold + hot total, seconds)
A pattern such as uvf 'osm17/*.osm' 東京 against ripgrep given several files (rg -z for compressed ones).
| Target | Lines hit | ripgrep | uvf | Ratio |
|---|---|---|---|---|
6 plain files (one of them the 51 GB japan-latest.osm) |
100,424 | 119.37 | 111.03 | 1.08 🟢 |
| 7 gz files | 122,441 | 44.70 | 37.27 | 1.20 🟢 |
| 13 plain + gz files | 222,865 | 133.66 | 144.64 | 1/1.08 🍊 |
13.5 One large file (total of seven searches, seconds)
Seven searches — plain, -i, -E, -E anchored at line start, -E -i, -v and -E -v — each measured cold and hot, then totalled.
| Data | ripgrep cold | uvf cold | ripgrep hot | uvf hot | ripgrep total | uvf total | Ratio (total) |
|---|---|---|---|---|---|---|---|
| 3G | 25.51 | 23.43 | 7.74 | 7.84 | 33.25 | 31.27 | 1.06 🟢 |
| 10G | 78.38 | 75.02 | 23.06 | 18.73 | 101.44 | 93.75 | 1.08 🟢 |
| 50G | 425.91 | 383.04 | 404.62 | 371.92 | 830.53 | 754.96 | 1.10 🟢 |
13.6 Reading the numbers
- Compressed files are on par with ripgrep in all seven formats (1/1.09–1.29×). On gz, lzma and br uvf is about 1.2× faster; only on xz is ripgrep slightly faster (about 8–9% at both 1G and 3G). Not launching external commands should give uvf an edge, but every gap is under 1.5×.
- For plain files, uvf is slightly faster on the cold run (reading from disk), and ripgrep is slightly faster on the hot run (reading from the cache) (0.33 s vs 0.44 s at 3G).
- Several files are on par too (1/1.08–1.20×). On the 13 mixed plain and gz files, ripgrep came out slightly faster.
- One large file: the seven-search totals are on par at 3G, 10G and 50G (1.06–1.10×).
- If you search the same file again and again, UwView Pro’s uvp, which builds an index to make later runs fast, is the better fit (see the “Performance” chapter of the uvp manual).
Related
- uvp command manual (UwView Pro’s CLI: an index makes later runs fast; narrowing, tallying, replacing)
- UwView User Guide (the free edition’s window) / UwView Pro User Guide
- Benchmarks / Download / Help (setting up
uvfon your PATH) - Original on GitHub (same content): uvf command manual (Japanese) / v1.9.0 release notes