Stop 02 · Node.js FundamentalsProjects · 2/3

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.

The mascot sorts a messy heap of clothes, books and chargers into three neat boxes.

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

Read folder
Find ext
Pick bucket
Make dir
Move 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

js
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

~30 min

Quick check

What does path.extname("report.final.PDF") return?

Go deeper

  1. 1Use `fs.promises.readdir` and `path.extname` to categorize files by type.
  2. 2Handle errors gracefully — permission issues, files in use.
  3. 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.

Download
InsideEdge