Turn a folder of meaningless research-paper downloads into a readable library.
1706.03762v7.pdf -> Vaswani - 2017 - Attention Is All You Need.pdf
10.2307_2025464.pdf -> Kuhn - 1998 - The Structure of Scientific Revolutions.pdf
download_8f3a2.pdf -> Smith - 2020 - Deep Learning Approaches for Something.pdf
It looks each paper up online (arXiv / Crossref) for authoritative metadata and falls back to reading the PDF itself, then writes renamed copies into a separate folder. Your originals are never touched, so a wrong guess costs you one manual rename — never a lost file.
- Accurate by default — an arXiv ID or DOI gets the real citation, not a guess.
- Handles awkward sources — theses, database cover pages, book excerpts, two-column journal layouts, PDFs with no space characters.
- Tells you what to check — anything uncertain is listed separately, with a reason.
- Private when you need it —
--offlinemakes a hard guarantee that nothing leaves your machine.
Requires Python 3.10+.
git clone https://github.com/Kashfy/paper-renamer.git
cd paper-renamer
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtThat pulls in a small (~15 MB) local language model used to recognize author names. Both online sources — arXiv and Crossref — are free, keyless public APIs, so there's no signup or API key anywhere.
Point it at a folder:
python -m paper_renamer ~/Downloads/papersRenamed copies land in ~/Downloads/papers/renamed/ and you get a report:
Renamed (3)
┌─────────────────────┬────────────────────────────────────────────────────────────────┬───────┐
│ Original │ New name │ From │
├─────────────────────┼────────────────────────────────────────────────────────────────┼───────┤
│ 10.2307_2025464.pdf │ Kuhn - 1998 - The Structure of Scientific Revolutions Revisit… │ text │
│ 1706.03762v7.pdf │ Vaswani - 2017 - Attention Is All You Need.pdf │ arxiv │
│ download_8f3a2.pdf │ Smith - 2020 - A Dissertation on Deep Learning Approaches for… │ text │
└─────────────────────┴────────────────────────────────────────────────────────────────┴───────┘
Needs a look (1)
┌───────────────┬──────────────────────────────────┬───────────┐
│ Original │ New name │ Why │
├───────────────┼──────────────────────────────────┼───────────┤
│ scan_0042.pdf │ The Nature of Normal Science.pdf │ no author │
└───────────────┴──────────────────────────────────┴───────────┘
Copied unchanged (1)
┌───────────────────┐
│ File │
├───────────────────┤
│ reading-notes.txt │
└───────────────────┘
5 file(s) copied into /Users/you/Downloads/papers/renamed
metadata from: text 3, arxiv 1
1 flagged above — rename by hand if wrong (originals untouched)
Confident renames go under Renamed. Anything worth a glance — a fuzzy title match, a missing author, nothing found at all — is collected under Needs a look with the reason, so you only inspect what's actually uncertain.
Common variations:
# Work entirely offline — no network calls at all
python -m paper_renamer ~/Downloads/papers --offline
# Write somewhere else, and include subfolders
python -m paper_renamer ~/Downloads/papers -o ~/Library/papers --recursive| Flag | Description |
|---|---|
-o, --output DIR |
Output folder for renamed copies (default <input>/renamed). |
--recursive |
Descend into subfolders. |
--offline |
Disable all network lookups; use only embedded PDF metadata and first-page text. Guarantees no network call is made. |
--mailto EMAIL |
Optional contact email for Crossref's polite request pool (better rate limits). Falls back to $PAPER_RENAMER_MAILTO. Never required. |
Naming follows Author - Year - Title.pdf. Missing pieces are dropped rather
than faked, so you may get 2017 - Some Title.pdf or just Some Title.pdf. If
nothing useful is found the original filename is kept — no file is ever left
unnamed, and name collisions get (2), (3) suffixes. Non-PDF files
(.epub, .djvu, …) are copied through unchanged.
Three layers, most authoritative first.
1. arXiv / Crossref lookup. An arXiv ID (from the filename or the stamp arXiv prints on the page) or a DOI is queried for the real citation. If neither is present, the extracted title is used for a Crossref bibliographic search as a last resort — that fuzzy match is accepted only above a similarity threshold and is always flagged for review, since it can land on the wrong paper.
2. Embedded PDF metadata. /Author, /Title, /CreationDate. Software
strings ("Microsoft Word") are discarded, as are journal names written into
/Title — PNAS and others do this. A /CreationDate in the current year is
ignored: it records when you downloaded or scanned the file, not when the work
was published.
3. First-page text. The largest-font line near the top becomes the title, and a plausible year is found by regex, preferring years next to "©" or "Published". Authors are located with a local spaCy NER model — it runs entirely on-device — that looks for actual person names below the title, rather than assuming the byline is the next line down.
That last layer is where awkward documents are handled:
| Situation | What happens |
|---|---|
| Thesis / dissertation | Degree boilerplate ("submitted in partial fulfillment of…") sits between title and byline; it's skipped instead of being read as the author. |
| Database cover page | JSTOR / ProQuest / EBSCO / repository sheets are detected and skipped, so you get the paper's title, not the database's name. |
| Mastheads & article labels | A "PNAS" logo or a "Notes and Discussion Piece" banner is often set larger than the real title, and is excluded from title candidacy — as are university names. |
| No space characters | Journal and LaTeX PDFs often place each word separately and emit no spaces. Word boundaries are inferred from spacing relative to font size, which is what stops titles coming out as NotesandDiscussionPiece. |
| Two-column layouts | Unrelated left- and right-column fragments at the same height are split apart rather than concatenated. |
| Book excerpts | A running book title, a "CHAPTER IV" label, and the chapter's own title are told apart, and no year is invented when the page has none. |
| Superscript markers | Affiliation markers ("Erin L. Murphy^a,b,1") are stripped from the surname, and a multi-author byline resolves to the first author. |
--offline is a hard guarantee, not a best effort: it disables the
arXiv/Crossref tier entirely, so no filename or PDF content ever leaves your
machine. The extraction code contains no network calls at all — the single
network entry point lives in cli.py behind that flag, and a test asserts it
is never reached when --offline is set.
In normal (online) mode, only an arXiv ID, a DOI, or an extracted title is sent
— never the file. The optional --mailto address goes to Crossref as a contact
header and is stored nowhere.
- No OCR. Image-only scans have no extractable text, so nothing can be read from them.
- English-only NER. The author model is English; non-English bylines are often missed.
- Fuzzy matches can be wrong. They're flagged for exactly this reason.
Since originals are never modified, the cost of any miss is one manual rename in the output folder.
pip install -r requirements-dev.txt
pytest78 tests, no network access required — the online tiers are exercised against mocked responses, and PDF layouts are built as in-memory fixtures rather than binary files.
- Native metadata extraction for
.epub/.djvu. - OCR fallback for scanned, image-only PDFs.
MIT.