File Organizer Script
Part of the Backend Developer Roadmap
In short
Your Downloads folder is a jungle of PDFs, screenshots and zip files. A script that sorts it is a perfect first fs project, and genuinely useful by the end of the evening.
A script that scans a directory and automatically sorts files into folders by type or date — practice for the `fs` module, path manipulation, and async iteration.

Think of it like this
Sorting your hostel cupboard
Shirts in one box, books in another, chargers and cables in a third. You pick up each item, decide what it is, and drop it in the right box. Your script does the same for files, using the extension instead of your eyes.
Watch it happen
The build plan, file by file
1/5readdir lists everything in the folder, with file types, so you can skip sub-folders.
The big ideas
What you need to know
Dry run first
A --dry-run flag prints what would move without touching anything. Run it before every real run.
Never overwrite
If the target already has a file with that name, skip it or add a suffix like (1). Never replace silently.
Keep going on errors
One locked or odd file shouldn't stop the run. Log it and move on to the next.
End with a summary
Print how many files went into each folder, so you can trust what the script did.
See it in code
Walk through the code
1import { readdir, mkdir, rename, access } from "node:fs/promises";2import path from "node:path";3const dir = process.argv[2] ?? ".";4const buckets = { ".pdf": "Documents", ".png": "Images", ".jpg": "Images", ".zip": "Archives" };5const dryRun = process.argv.includes("--dry-run");6 7for (const entry of await readdir(dir, { withFileTypes: true })) {8 if (!entry.isFile()) continue;9 const bucket = buckets[path.extname(entry.name).toLowerCase()] ?? "Others";10 const target = path.join(dir, bucket, entry.name);11 if (await access(target).then(() => true, () => false)) continue; // never overwrite12 console.log(`${entry.name} -> ${bucket}/`);13 if (dryRun) continue;14 await mkdir(path.join(dir, bucket), { recursive: true });15 await rename(path.join(dir, entry.name), target);16}1/4The folder to sort, the extension-to-bucket map, and the dry-run switch.
Run node organize.mjs ./test-folder --dry-run first to see the plan, then without the flag. rename fails with EXDEV across different drives; copy then delete in that case.
Save yourself the pain
Common mistakes
Oops
Testing the script on your real Downloads folder first.
Do this instead
Make a test folder full of dummy files. One wrong path in rename can scatter hundreds of real files.
Oops
Letting one bad file crash the whole run.
Do this instead
Wrap each move in try/catch, log the failure with the file name, and carry on with the next file.
Your mission
First milestone: a safe dry run
Quick check
What does path.extname("report.final.PDF") return?
Go deeper
- 1Use `fs.promises.readdir` and `path.extname` to categorize files by type.
- 2Handle errors gracefully — permission issues, files in use.
- 3Add a `--dry-run` flag that previews changes without moving any files.
More projects at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.