Search the text inside the files in a folder, on demand. Point it at a directory, type what you remember, and get every line that contains it, grouped by the file it came from.
It builds no index, installs no service, and watches nothing in the background. That is the point: it is the tool you reach for on the day Windows Search returns filenames and nothing else.
- Searches file contents, right now. No indexer to wait for, no catalog to go stale, no folders to opt in ahead of time.
- Groups hits by file, collapsible, with the match highlighted in place and optional context lines above and below, ordered by name or by modified date, size, or hit count.
- Streams results as it goes, with a Cancel button that actually stops the scan rather than hiding it.
- Understands terminal logs. Raw session logs carry ANSI escapes; RSFind strips them before matching, so a phrase that straddles a color code is still findable and the results read like the terminal did.
- Reads inside
.xlsxand.docx, with no Office install and no dependency. A spreadsheet hit reports itself asSchedule!A2- a reference you can paste into the Name Box - and a document hit asParagraph 1orHeader 1, paragraph 1. - Names the formats it cannot read instead of returning nothing. A folder of PDFs that answers "no hits" is a missing capability wearing the clothes of an answer.
- Handles encodings that trip other tools. UTF-8 with or without a BOM, UTF-16 and UTF-32 with one, and old ANSI exports, all in the same folder.
- Adds itself to the folder right-click menu, per user, without admin.
Build it with the C# compiler already inside Windows. There is no SDK to install, nothing to restore, and no network access at any point:
Build-RSFind.cmdThen run RSFind.exe. To put it in Explorer, open Menu > Add to Explorer
Right-Click Menu; right-clicking a folder (or the empty space inside one)
then offers Find Text with RSFind, which opens the app already pointed at
that folder. The same menu item removes it again.
You can also pass a folder on the command line: RSFind.exe C:\logs.
Run-From-Source.cmdCompiles the sources in memory and runs the same app with no executable
involved. It takes a folder too: Run-From-Source.cmd C:\logs.
This exists because an executable is a thing people have to decide to trust.
A freshly built, unsigned binary has no reputation, and machines configured to
be careful about that are being sensible. Handing someone a folder of .cs
files they can read costs nothing extra here, because the compiler is already
on their machine.
It is slower and heavier - measured on this project, about 1.6 s to a window against 0.4 s, and 96 MB against 37 MB, because it compiles on every launch. Use the exe day to day.
The Explorer entry needs the exe. That entry records which program to launch, and from the source path that would be PowerShell - a right-click item that opens a console window under a registry key named RSFind. RSFind refuses to write it rather than writing it wrong, and says so.
| Option | What it does |
|---|---|
| Match case | Off by default, so Serial finds SERIAL. |
| Match whole word | nvme0 stops matching inside nvme0n1. |
| Use regex | .NET regular expressions. A half-typed pattern reports itself on the summary line instead of throwing. |
| Include subfolders | On by default. |
| Exclude binary files | On by default. A NUL byte in the first 8 KB means binary - unless a byte-order mark says otherwise, because UTF-16 text is half NUL bytes. |
| Strip ANSI escapes | On by default. See the note below. |
| File mask | *.log;*.txt - semicolons, commas, or spaces all separate. Blank means every file. A bare .log is read as *.log. |
| Exclude | Same syntax, applied first. Exclude beats include. |
| Skip over | Files larger than this many MB are not read. 0 means no limit. |
| Context lines | How many lines to show before and after each hit. |
Preferences live in %APPDATA%\RSFind\settings.ini, which is a plain
key=value file you can read and edit. Search queries are never written
there, and no history of past searches is kept. A query typed against a
folder of console logs is as likely to be a serial number, a hostname, or a
password as it is to be smartctl, and a search tool that quietly keeps a list
of everything you looked for is a tool you have to think about before using.
Strip ANSI escapes is on. Terminal session logs are full of escape sequences; with stripping off, every prompt line renders as a row of boxes and a phrase that spans a color code cannot be matched at all. Turn it off when you want to see exactly what is in the bytes. It is one checkbox either direction.
Results are capped at 5,000 hits per file and 200,000 in total. A search for a common word across a log folder is one keystroke away, and the cap is what keeps that from becoming a memory problem. Whenever a cap bites, the summary line says so - a short list that does not admit it is short reads as "that is all there is", which is the one thing a search tool must never imply.
.xlsx, .xlsm, .docx, and .docm are ZIP archives full of XML, and both a
ZIP reader and an XML reader ship inside Windows. So this costs two in-box
references rather than an Office install, an interop assembly, or a package you
would have to trust.
These files are handled before the binary check, not after - a workbook is a ZIP, a ZIP is full of NUL bytes, and the binary sniff is right about that. The order is what stops the exclude-binary default from silently discarding the one format this feature exists to read.
What is worth knowing about what comes out:
| Spreadsheet cells | Reported as Sheet name!B14. Shared strings, inline strings, numbers, and cached formula results are all searched. |
| Formulas | Not searched. Searching them would answer SUM with every totaled column in the workbook. A formula cell yields its result; an uncalculated one yields nothing. |
| Dates | Stored by Excel as serial numbers, and searched as stored. Searching for 2026-09-14 will not find a real date cell - search the text around it. |
| Word paragraphs | Runs are joined first, so a phrase still matches when Word split it across runs at a formatting change. That splitting is why a naive reader cannot find a sentence containing one bolded word. |
| Headers, footers, footnotes, endnotes, comments | All searched, and labeled. A change number or a classification marking usually lives in a header, and that is exactly what people search a folder of documents for. |
| Tracked deletions | Skipped. Text inside a w:del is not in the document any more, and matching it reports a phrase that is not there when the file is opened. |
| Context lines | Not offered for these formats. The cell above a hit is not context the way the line above one is. |
Double-clicking one of these opens the file with its normal application, and
ignores any editor command you have set - handing a workbook to a text editor
with a -n14 argument opens a ZIP as text at line 14.
.xls, .doc, .ppt, .pptx, .pdf, .rtf, .odt, and .ods are not
read. They are counted separately and named on the summary line, so the number
you get back is never quietly incomplete.
Type a replacement, press Replace..., and read what would change before anything is written. The ellipsis is the promise: that button opens a preview rather than acting, and the preview is not a confirmation step bolted on - it is the only path through the feature.
It preserves the case of what it replaced. colour becomes color,
Colour becomes Color, and COLOUR becomes COLOR. This is what makes a
British-to-American pass over a documentation folder produce a clean diff
instead of a hundred new sentence-case mistakes. It only reshapes a replacement
you typed entirely in lower case: one carrying its own capitals - RSFind,
macOS - was written that way on purpose and is used literally. Turn the whole
behavior off with the Preserve case checkbox.
One honest caveat the tool cannot solve for you: substring replacement is right
for colour, which carries colours and coloured along correctly, and wrong
for grey, which would take greyhound with it. Match whole word is the
mitigation and the preview is the backstop.
Refused files appear in the preview with their reason, greyed out. They are never hidden - a file that silently declines to change is the worst possible outcome here.
| Refused | Why |
|---|---|
| A file changed since the search | Three checks: size, timestamp, and re-reading every line being edited. The last one catches an edit that kept the same size and restored the timestamp. |
| A file the search stopped counting early | The per-file cap is 5,000 matches. A file holding more than that is refused rather than partly replaced, because replacing what was found would leave the rest behind and report a number that sounds complete. |
| An Office file | The text was extracted from a ZIP. Writing it back would destroy the file. |
| A file whose escapes were stripped | The match positions point at cleaned text, not at the bytes on disk. Turn off Strip ANSI escapes and search again. A file containing no escapes is unaffected and can still be replaced. |
| A binary | Regardless of the exclude-binary setting. Unchecking that box to find a string inside a firmware image is not a request to rewrite it. |
| A replacement the encoding cannot store | An ANSI codepage silently turns what it cannot store into a question mark and reports success. Refusing beats losing the character. |
Every run copies the original files into %APPDATA%\RSFind\undo\<timestamp>\
before writing. Menu > Undo Last Replace puts them all back as a unit, and
skips any file that has been edited since - restoring over someone's later work
would be a worse mistake than the one being undone.
The last 10 runs are kept; older ones are removed on startup and after each replace. That folder holds complete copies of files you have changed, which is more sensitive than the search queries this tool deliberately refuses to write down - so it is bounded, and its location is said out loud here and in the About box rather than left to be discovered.
- Runs are capped at 5,000 changes. Above that the preview stops being a preview, so RSFind refuses and asks you to narrow the search instead of showing a sample and implying the rest was reviewed.
- Files are written through a temporary file and swapped, so an interrupted write leaves the original intact rather than half a file.
- The file comes back with its encoding, byte-order mark, and line endings exactly as they were. Only the matched spans change.
- In regex mode,
$1and friends are substituted. In literal mode a replacement containing$1is written exactly as typed. - When several matches land on one line, each preview row shows that one
change against the original line - so no single row shows the line as it
will finally read. Replacing
nvme0withnvme1oncheck nvme0 then nvme0 then nvme0previews as three rows, each with one substitution made, and writescheck nvme1 then nvme1 then nvme1. Every row is accurate about its own change, which is what makes the per-row checkboxes mean something; showing the cumulative line instead would make each row depend on which other boxes are ticked.
Ctrl+F narrows what is on screen. A search across a hundred session logs answers with a thousand hits, and the next question is usually "which of these was on LAB4" - a question about the results, not a reason to search the disk again. Type a host, an address, or a timestamp and the pane shows only what matches, with a count of what it is hiding. Escape puts everything back.
It filters rather than stepping match to match, because a host appears on dozens of rows: find-next would mean pressing it dozens of times, where a filter answers in one go and leaves a short list to double-click. Enter moves focus into that list.
A filter matching a filename keeps that file's hits whole, since the host is in the name rather than in any of the matched lines. A filter matching a line keeps that hit on its own.
Files are listed in a defined order, by filename unless you say otherwise. The Sort by and Ascending / Descending dropdowns at the end of the options row offer Modified, Created, Size, and Hit Count as well; the same choices live under right-click > Sort by on the results. Either one follows the other, and the choice is remembered.
Hit Count is the one worth knowing about: it answers "which of these files actually discusses this" rather than "which of them mentions it once".
Created is offered because people ask for it, and it is worth knowing what Windows means by it. It records when the file arrived at that path, not when its contents were made - copy a log off a device and its creation date is the day it landed on your disk, routinely newer than the date it was written. Modified is almost always the one that answers the question.
The order is applied when a scan finishes rather than while results stream in, so rows do not rearrange themselves under you while you are reading them. If you had scrolled, the file you were reading stays at the top; if you had not, the list stays at the top. A selected line stays selected and moves to wherever it now lives.
Each file's header shows its modified date and size, held against the right edge rather than trailing the filename, so they line up into a column you can read down. Dates that start wherever the previous filename happened to end have to be found before they can be compared.
Right-click the results for Copy Selected, Copy All Results, Copy Path, Open Containing Folder, Find in Results, and Expand or Collapse All. Copy All Results is for pasting a whole result set into a second file and reading it there. It copies everything the filter admits, whether or not a group happens to be collapsed - collapsing is a way to get a long list out of the way while reading, not a statement about what you want to keep.
Double-click a hit, or press Enter. Double-clicking a file header opens that file too, at its first match rather than at line 1. To collapse a group, click the triangle in the indent to its left, or use the left and right arrow keys.
By default the file opens with whatever Windows associates. To jump straight to
the line, set an editor command under Menu > Editor Command, using {file}
and {line} as placeholders:
notepad++ {file} -n{line}
RSFind will not launch an executable. With no editor command set, opening a
hit hands the path to Windows, which runs a .exe, .bat, .ps1, .js,
.lnk, .reg and the rest rather than opening them - and those turn up in
results as soon as you blank the file mask or uncheck Exclude binary files
to search inside an image. Those are refused with a line saying so. The machine's
own PATHEXT is honored too, so an extension your box treats as executable is
refused even if it is not on the built-in list.
An editor command sidesteps this entirely: handing a path to a text editor does not execute it, so with one set you can open anything. Open Containing Folder on the right-click menu is the other way round it.
Nothing is installed, no service is registered, nothing is added to startup, and nothing goes out on the network. What it writes is this, and this is all of it:
| What | Where | When |
|---|---|---|
| Preferences | %APPDATA%\RSFind\settings.ini |
On exit. Plain key=value, under 1 KB, and no record of what you searched for. |
| Undo copies | %APPDATA%\RSFind\undo\<timestamp>\ |
On every replace. The last 10 runs are kept; older ones are removed. |
| A temporary file | <the file>.rsfind-tmp, beside the file being replaced |
During a replace, removed when it succeeds. |
| The original, renamed aside | <the file>.rsfind-old, likewise |
Only when the swap fails and RSFind falls back to a rename. |
| An exported result list | Wherever you point the Save dialog | Only from Menu > Export Results. |
| Two registry keys | HKCU\Software\Classes\Directory\shell\RSFind and the same under Directory\Background |
Only if you turn on the Explorer entry, and removed when you turn it off. |
The undo folder is the one that grows. It holds complete copies of the files you have changed, so a replace across a hundred documents puts a hundred documents in your profile. It is capped rather than unbounded, and deleting it is safe at any time - it costs only the ability to undo past replaces.
Nothing is written to %TEMP%. The one exception is Run-From-Source.cmd,
which compiles on launch: the in-box C# compiler writes seven scratch files
there and removes them within a second. The exe does not do this at all.
If a replace is interrupted - the machine loses power, the process is killed -
a .rsfind-tmp can be left behind. That is deliberate: a stray temp file is a
better outcome than a moment where your file does not exist. It is safe to
delete, and the name makes it easy to find.
The only programs it starts are the ones you ask it to: Explorer for Open Containing Folder, and whatever opens a result you double-click. See above for what it refuses to launch.
- No index and no background service. Nothing runs when the window is closed, so there is nothing to trust, nothing to update, and nothing that could have been reading your disk while you were not looking.
- No network access, ever. No update check, no telemetry, no crash reporting. The binary references only assemblies that ship with Windows.
- No replace without a preview. There is no command-line replace, no "replace all" that skips the window, and no way to reach the write path except by reading what it would do. That is deliberate: it is the one button here that can quietly damage a directory.
- No
.xls,.doc, or.pdf. The modern zipped formats are read; the older binary ones and PDF are not, and RSFind says so on the summary line rather than letting them count as searched. - No search history. See above.
Windows with .NET Framework 4.x, which every supported version of Windows already has. Nothing else.
The Unlicense. See LICENSE.

