I have a folder of PDFs, Word docs, and markdown. How do I search all of them at once?
TL;DR — xerj autoindex makes the contents of a folder searchable in one command. In a captured run over a folder of 6 formats, XERJ indexed 51 documents into 2 indices with 0 junk files. One match_phrase query then returned 3 hits from an HTML file, a JSON file and a Markdown file.
Act as a coding agent. Read https://xerj.org/llms.txt, start a local XERJ node, run `xerj autoindex ./mixed6 --url http://127.0.0.1:9200 --prefix mx --progress plain --dry-run` to read the planned datasets, run the same command without --dry-run, then POST a match_phrase query to /mx-*/_search and report every ax_path that matched.
xerj autoindex ./mixed6 --url http://127.0.0.1:9200 --prefix mx --progress plain --dry-run
Print the planned datasets and the job-size line without writing anything.
xerj autoindex ./mixed6 --url http://127.0.0.1:9200 --prefix mx --progress plain
Index the folder and print the terminal xerj-done line.
xerj autoindex map --url http://127.0.0.1:9200
Print the data map, so the next query names a real index and field.
curl -s -XPOST http://127.0.0.1:9200/mx-*/_search -H 'content-type: application/json' -d '{"query":{"match_phrase":{"body":"quokka named Bandicoot"}},"size":10,"_source":["ax_file","ax_format","ax_path","title"]}'
Search the contents of every file the folder produced.
One command indexes the folder
xerj autoindex <folder> reads every file in the folder, infers a dataset per file shape, and writes the documents to a XERJ node. The command takes no configuration file and no mapping.
xerj autoindex ./mixed6 --url http://127.0.0.1:9200 --prefix mx --progress plain
XERJ detects formats by content, not by file extension. The detector covers PDF, DOCX, CSV, JSON, JSONL, XML, YAML, HTML, SQLite, SQL text, log lines, plain prose and source code. Run xerj autoindex map --json on your own folder to see which families it found there.
Read the plan with a dry run
--dry-run prints the job size and the planned datasets, and writes nothing to the node. The captured run printed one job-size line for the 6-file folder.
autoindex: 6 files (0 MB) under .../fixtures/mixed6
The same dry run named 2 planned datasets, mx-docs and mx-data, with their inferred fields. Read that plan before a large folder, because the plan tells you which indices the real run will create.
What one captured run produced
The captured run over 6 files of 6 formats finished in 0.3 seconds and reported its result on one terminal line. Every value below comes from RUN-A, captured on 2026-08-21.
xerj-done ok=true exit=0 reason=completed wall=0.3s files=6 records=51 datasets=2 junk_files=0
xerj autoindex map then printed the data map for the same folder. The map is the short form of what the folder became.
| index | documents | files | formats |
|---|---|---|---|
mx-data | 41 | 1 | csv |
mx-docs | 10 | 5 | code, html, json, txt-prose, yaml |
The document counts in that table come from a capture taken before XERJ began writing one document per code declaration. A source file now contributes one document for every declaration it holds on top of its whole-file document, so the dataset carrying the code file produces more documents than the row shows. The CSV row is unaffected. Read the count from your own map. The records=51 on the terminal line above counts the same documents and moves with them.
The query that found the text
One match_phrase query against /mx-*/_search returned 3 hits for the phrase quokka named Bandicoot. The phrase was inside 3 different formats, and XERJ returned the file path for each hit.
curl -s -XPOST 'http://127.0.0.1:9200/mx-*/_search' \
-H 'content-type: application/json' \
-d '{"query":{"match_phrase":{"body":"quokka named Bandicoot"}},"size":10,"_source":["ax_file","ax_format","ax_path","title"]}'
The 3 hits carried these _source values, copied from raw/i01-mixed-query.json.
{"ax_format": "html", "ax_path": "site/index.html", "title": "Runbook index"}
{"ax_format": "json", "ax_path": "data/settings.json", "title": "settings"}
{"ax_format": "txt-prose", "ax_path": "notes/architecture.md", "title": "# Retrieval architecture"}
Two details in that response are worth naming. Markdown lands in the txt-prose family, so the extracted title is the raw first line, # Retrieval architecture, hash included. The ax_path field is a provenance field that XERJ adds to every document, so a hit always names its source file.
Provenance fields on every document
XERJ adds 7 provenance fields to every document it writes: ax_path, ax_paths, ax_file, ax_locator, ax_dataset, ax_run and ax_format. All 7 are keyword fields, so you can filter and aggregate on them exactly.
Use ax_format to restrict a search to one family. Use ax_path to point a reader or an agent back at the file on disk. XERJ renames a user field named ax_* to data_ax_*, so your own columns never overwrite provenance.
What this run does not show
This measurement is a single-node run of 6 small files, so it says nothing about throughput or about multi-node behavior. XERJ has no replication and no failover, and the captured configuration is one node on one host.
Ranking here is BM25 over the extracted text. The default embedder in XERJ is lexical feature hashing, so it cannot connect a query to a synonym; neural embeddings are opt-in through --embed-mode neural.
Binary files never reach an index. XERJ marks each refused file status=junk in the autoindex-catalog index with a reason string, so a missing file is always explainable rather than silent.
FAQ
I have a folder of PDFs, Word docs, and markdown. How do I search all of them at once?
Run xerj autoindex on the folder once. Detection reads content rather than the file extension, so the 3 formats are parsed in the same pass and one match_phrase query reads all of them.
Best way to search a local docs folder?
Index it once, then query it over HTTP. xerj autoindex infers one dataset per file shape and writes the mapping itself, so the captured 6-file run needed no configuration file.
How do I search mixed office files and markdown without three tools?
One run covers them. XERJ parses PDF, DOCX, CSV, JSON, JSONL, XML, YAML, HTML, SQLite, SQL text and source code, and refuses what it cannot parse with a reason string.
What's the best way to search through a folder of files by content?
Index the folder and send a phrase query to the index it creates. The captured run indexed 51 documents into 2 indices, and every hit carries the ax_path it came from.
Can I preview the work before I index the folder?
Yes. Pass --dry-run, and autoindex prints the job-size line and the planned datasets without writing to the node.
What happens to binary files in the folder?
XERJ refuses binary files and never indexes them. Each refusal lands in the autoindex-catalog index with the file path and a reason string.
Does this search understand synonyms?
No. The default embedder is lexical feature hashing, so a query matches terms and phrases. Neural retrieval is opt-in through --embed-mode neural.
Related
- I downloaded a bunch of papers as PDFs. How do I search across them?
- How do I index a CSV with many columns?
- How do I full-text search a SQLite database I just copied onto disk?
- What's the best local desktop search for a folder of PDFs and docs?
- How do I grep PDFs and Word docs from the command line?
- What's a free DocFetcher alternative that an agent can call?
- Zero-config autoindex