Keep a self-updating contents file per folder
Auto-create a `_contents.md` Doc inside every Northwind folder, refreshed nightly.
Publié le 13 nov. 2025
Northwind’s project folders fill up over the life of a job — briefs, drafts, exports, contracts — and the only way to see what is inside one is to open it in Drive and scroll. That is fine until someone needs a quick overview without Drive access, or wants a printable index of a finished project, or is browsing the folder structure on their phone.
This script drops a _contents Doc into every folder it walks and keeps it
current. The Doc lists every file in that folder as a clickable link, refreshed
nightly so it never drifts out of date. Each folder ends up self-documenting: open
the contents Doc and you see the folder without opening the folder.
What you’ll need
- A root folder to index. The script walks it and every subfolder, and writes a contents Doc into each one.
- The folder’s ID — the string in its URL after
/folders/. - Nothing else. The script creates each
_contentsDoc itself using the Docs service, which every Google account has.
The script
// The Drive folder to index. The script recurses into every subfolder.
const ROOT_FOLDER_ID = '1abcRootFolderId';
// The name of the contents Doc placed inside each folder. It is also
// skipped when listing files, so it never lists itself.
const CONTENTS_DOC_NAME = '_contents';
/**
* Entry point. Walks the root folder and refreshes a contents Doc
* inside it and every subfolder beneath it.
*/
function refreshContentsFiles() {
walk(DriveApp.getFolderById(ROOT_FOLDER_ID));
}
/**
* Builds or refreshes the contents Doc for one folder, then recurses
* into its subfolders.
*/
function walk(folder) {
// 1. Find an existing contents Doc, or create a fresh one.
const existing = folder.getFilesByName(CONTENTS_DOC_NAME);
const hadDoc = existing.hasNext();
const doc = hadDoc
? DocumentApp.openById(existing.next().getId())
: DocumentApp.create(CONTENTS_DOC_NAME);
// 2. A newly created Doc lands in My Drive — move it into this folder.
if (!hadDoc) DriveApp.getFileById(doc.getId()).moveTo(folder);
// 3. Clear the Doc and give it a title naming the folder.
const body = doc.getBody();
body.clear();
body.appendParagraph('Contents of ' + folder.getName())
.setHeading(DocumentApp.ParagraphHeading.TITLE);
// 4. List every file in the folder as a linked bullet, skipping the
// contents Doc itself.
let count = 0;
const files = folder.getFiles();
while (files.hasNext()) {
const f = files.next();
if (f.getName() === CONTENTS_DOC_NAME) continue;
body.appendListItem('').appendText(f.getName()).setLinkUrl(f.getUrl());
count++;
}
// 5. Note an empty folder explicitly so the Doc is never blank.
if (count === 0) body.appendParagraph('(empty folder)');
doc.saveAndClose();
// 6. Recurse into every subfolder.
const subs = folder.getFolders();
while (subs.hasNext()) walk(subs.next());
}
How it works
refreshContentsFilesis the entry point — it just callswalkon the root folder.walklooks for an existing_contentsDoc in the folder. If one exists it reuses it; if not it creates a new Doc, which keeps the same URL across runs so links to it stay stable.- A freshly created Doc is born in My Drive, so the script moves it into the folder it belongs to.
- It clears the Doc body and writes a title naming the folder, so the Doc reads well even printed on its own.
- It walks the folder’s files and adds each as a bulleted, linked item — skipping the contents Doc so it never lists itself. An empty folder gets an explicit “(empty folder)” line instead of a blank page.
- It saves the Doc, then recurses into every subfolder so the whole tree ends up indexed.
Example run
Take a project folder Acme — Q3 campaign holding three files. After a run, the
_contents Doc inside it reads:
Contents of Acme — Q3 campaign
- Brief.gdoc
- Brand deck v4.pptx
- Shoot schedule.gsheet
Each bullet is a live link straight to the file. A subfolder Acme — Q3 campaign/Exports gets its own _contents Doc listing only that subfolder’s
files — every level of the tree is documented independently.
Trigger it
Run this nightly so each folder’s contents Doc reflects the day’s changes:
- In the Apps Script editor, open Triggers (the clock icon).
- Click Add Trigger.
- Choose
refreshContentsFiles, event source Time-driven, type Day timer, and a quiet hour such as 2am to 3am. - Save, and approve the authorisation prompt the first time.
Watch out for
- The script rebuilds each Doc from scratch every run. Do not hand-edit a
_contentsDoc expecting your notes to survive — anything you add is wiped on the next refresh. - It lists files but not subfolders. Each subfolder gets its own contents Doc
instead; if you want subfolders named in the parent Doc too, add a second loop
over
folder.getFolders(). - Creating and opening a Doc per folder is relatively slow. A few hundred folders is comfortable; many thousands may approach the six-minute runtime limit. If you hit it, index one subtree per run.
- Every refresh counts as an edit on every Doc, so the contents Docs themselves will appear in any Drive activity report. That is expected — just be aware they add noise to audits.
- The Docs created here are real Google Docs, despite the
.mdin the article title. There is no native Markdown file type in Drive; a Doc is the closest printable, linkable equivalent.
À voir aussi
Build a recurring file-delivery system
Drop a fresh report file into a Northwind client folder weekly — they don't even ask.
Mis à jour le 15 déc. 2025
Build a Drive search index in Sheets
Make Northwind's file metadata searchable in a Sheet — like Spotlight for Drive.
Mis à jour le 7 déc. 2025
Build a shared-folder onboarding kit
Auto-grant new Northwind hires the folders they need on day one.
Mis à jour le 29 nov. 2025
Route saved email attachments to project folders
File Gmail attachments into the right Northwind client folder based on subject keywords.
Mis à jour le 25 nov. 2025
Bundle a folder of images into one PDF
Combine Northwind scans into a single deliverable PDF using a generation service.
Mis à jour le 17 nov. 2025