A book is an awkward size for a single text file while it is being written, and an awkward size for fifty files when it is being typeset. The working arrangement is both: chapters as files, the book as a concatenation you generate when you want to see the whole thing.
Name the files so order is free
The only trick that matters before any command. Zero-pad the numbers and put nothing in front of them that sorts alphabetically in the wrong place.
00-title-and-copyright.md
01-introduction.md
02-the-first-mistake.md
03-a-worked-example.md
14-appendix.mdchapter-2.md and chapter-10.md will sort as 10 then 2, which you will notice exactly once, in the exported PDF, after you have already proofed the wrong order. 02 and 10 will not. Front matter starts at 00 so it stays first without a special case.
Concatenate, then typeset
On a Mac or Linux machine, from the folder of chapters:
for f in *.md; do
cat "$f"
printf '\n\n---\n\n'
done > book.mdThat prints each file, then a blank line, a --- page-break marker, and another blank line. The last --- makes an empty trailing page — delete it. Windows PowerShell is the same idea: Get-ChildItem *.md | ForEach-Object { Get-Content $_; "nn---nn" } | Set-Content book.md.
Pandoc will do this in one step if you are already in that toolchain — pandoc *.md -o book.pdf — and it has its own ways to insert breaks. If the destination is a tool that wants one Markdown file, concatenate first and hand it book.md.
The heading trap
Each chapter file was probably written with its own # Chapter title at the top, because in isolation that is the title. Concatenate ten of those and the book now has ten # headings. In a renderer that starts a new page on every # — bukpress does, except for the first — you get the page breaks you wanted for a different reason, and an EPUB whose navigation is ten top-level entries with no book title.
Pick a convention and apply it before you merge:
#only in00-title-and-copyright.md, once, for the book title.##at the top of every chapter file.###for sections inside a chapter.
A one-line check after concatenating: count the # headings that are not ## or ###. There should be one. The contents page is generated from this outline, so a messy merge is a messy table of contents in every format at once.
What not to merge
- Notes, scraps, unused chapters. If it is in the folder, it is in the book. Keep a
_drafts/ornotes/directory that the glob does not see. - A README.
README.mdsorts in the middle of a case-sensitive glob on some systems and at the start on others. Either way it is not a chapter. - Cover artwork. A cover is not Markdown. Attach it as a cover; do not inline it as the first image.
- Per-chapter bibliographies unless you have a real citation tool. Ten copies of the same reference list is the usual result of merging academic chapters that each ended with "References".
Obsidian, Notion, and other vaults
If the chapters are notes in a vault, the merge is the same and the export is the extra step. Obsidian: a plugin or a simple cat on the vault folder, after you have resolved [[wikilinks]] to something a normal Markdown renderer will accept — the longer Obsidian path. Notion: export the pages as Markdown, then concatenate; Notion's export is messy in predictable ways, covered in Notion to a book.
Do not try to typeset the vault directly. A vault is a graph. A book is a sequence. The concatenation is the moment you admit which one you are making.
Then it is one manuscript
From here the pipeline is the same as if you had written in one file all along: structure, design, export, proof. The whole map. In bukpress you paste or drop that combined file into a project; there is no multi-file book format, which is why the concatenation lives on your side. The preview will show whether the --- between chapters is doing what you meant, and whether a leftover # just started a blank page you will otherwise find in the PDF.