๐ File System Management in Node.js
The Story of the Digital Librarian
Imagine youโre a librarian in a magical library. This library has rooms (folders), books (files), and you have special powers to:
- Build new rooms
- Peek inside rooms to see whatโs there
- Move books around
- Throw away old books
- Check if a book is readable or locked
- Watch for changes when someone edits a book
Thatโs exactly what Node.js fs module does! Itโs your superpower toolkit for managing files and folders on a computer.
๐๏ธ Creating Directories
What is it?
Creating a directory = Building a new room in your library.
The Magic Words
const fs = require('fs');
// Create a single folder
fs.mkdirSync('my-folder');
// Create nested folders (like rooms inside rooms)
fs.mkdirSync('parent/child/grandchild',
{ recursive: true }
);
Why recursive: true?
Without it, Node.js panics if the parent folder doesnโt exist. With it, Node.js builds all the rooms needed, one inside another.
graph TD A["parent"] --> B["child"] B --> C["grandchild"]
Real Life Example
// Create a folder for user uploads
fs.mkdirSync('./uploads/images',
{ recursive: true }
);
console.log('Folder ready!');
๐ Reading Directory Contents
What is it?
Reading a directory = Looking inside a room to see all the books.
The Magic Words
// Get list of items in a folder
const items = fs.readdirSync('./my-folder');
console.log(items);
// ['file1.txt', 'file2.txt', 'subfolder']
Want More Details?
const items = fs.readdirSync('./my-folder',
{ withFileTypes: true }
);
items.forEach(item => {
if (item.isDirectory()) {
console.log('๐ Folder:', item.name);
} else {
console.log('๐ File:', item.name);
}
});
Why This Matters
You can build file explorers, backup tools, or find specific files in a folder!
๐๏ธ Deleting Files and Directories
What is it?
Deleting = Throwing away a book or an entire room.
Deleting a Single File
fs.unlinkSync('old-file.txt');
console.log('File deleted!');
Deleting a Folder
// Delete empty folder
fs.rmdirSync('empty-folder');
// Delete folder with everything inside
fs.rmSync('folder-with-stuff',
{ recursive: true }
);
โ ๏ธ Warning!
Thereโs no trash bin. Once deleted, itโs gone forever! Be careful.
graph TD A["Delete Command"] --> B{Is it a file?} B -->|Yes| C["Use unlinkSync"] B -->|No| D{Empty folder?} D -->|Yes| E["Use rmdirSync"] D -->|No| F["Use rmSync with recursive"]
๐ Moving and Copying Files
Moving Files
Moving = Picking up a book and placing it in another room.
// Move file to new location
fs.renameSync(
'old-location/file.txt',
'new-location/file.txt'
);
Copying Files
Copying = Making a photocopy of the book.
fs.copyFileSync(
'original.txt',
'backup.txt'
);
console.log('Copy created!');
Copy Modes
// Don't overwrite if file exists
fs.copyFileSync(
'source.txt',
'dest.txt',
fs.constants.COPYFILE_EXCL
);
| Mode | What It Does |
|---|---|
| Default | Overwrites existing file |
COPYFILE_EXCL |
Fails if destination exists |
COPYFILE_FICLONE |
Uses copy-on-write (faster) |
๐ Getting File Information
What is it?
Getting info = Reading the bookโs cover - size, creation date, type.
The Magic Words
const stats = fs.statSync('myfile.txt');
console.log('Size:', stats.size, 'bytes');
console.log('Created:', stats.birthtime);
console.log('Modified:', stats.mtime);
console.log('Is file?', stats.isFile());
console.log('Is folder?', stats.isDirectory());
Key Properties
| Property | Meaning |
|---|---|
size |
File size in bytes |
birthtime |
When file was created |
mtime |
Last modified time |
atime |
Last accessed time |
mode |
Permissions (read/write) |
Check If Something Exists
if (fs.existsSync('config.json')) {
console.log('Config found!');
} else {
console.log('Creating default config...');
}
๐ File Permissions and Access
What is it?
Permissions = Who can read, write, or enter a room.
Understanding Permissions
Think of it like a security guard checking:
- Read - Can you look at the book?
- Write - Can you edit the book?
- Execute - Can you run the book as a program?
Check Access
try {
fs.accessSync('file.txt', fs.constants.R_OK);
console.log('You can read this file!');
} catch (err) {
console.log('No read access!');
}
Permission Constants
| Constant | What It Checks |
|---|---|
F_OK |
File exists |
R_OK |
Can read |
W_OK |
Can write |
X_OK |
Can execute |
Change Permissions
// Make file read-only (owner read/write)
fs.chmodSync('secret.txt', 0o644);
graph TD A["File Access"] --> B["Owner"] A --> C["Group"] A --> D["Others"] B --> E["Read/Write/Execute"] C --> F["Read/Execute"] D --> G["Read Only"]
๐ซ File Descriptors and Flags
What is it?
A file descriptor is like a library card number - a special ID for an open file.
Opening Files with Descriptors
// Open file for reading
const fd = fs.openSync('data.txt', 'r');
// Read using the file descriptor
const buffer = Buffer.alloc(100);
fs.readSync(fd, buffer, 0, 100, 0);
// Always close when done!
fs.closeSync(fd);
Common Flags
| Flag | Meaning | Likeโฆ |
|---|---|---|
'r' |
Read only | Just looking at the book |
'w' |
Write (creates/overwrites) | Writing a new book |
'a' |
Append | Adding pages to end |
'r+' |
Read and write | Reading and editing |
'wx' |
Write, fail if exists | Donโt replace existing |
Why Use Descriptors?
- More control over reading/writing
- Better performance for many operations
- Can read/write at specific positions
// Write at specific position
const fd = fs.openSync('file.txt', 'r+');
const data = Buffer.from('Hello');
fs.writeSync(fd, data, 0, data.length, 10);
fs.closeSync(fd);
๐ Watching File Changes
What is it?
Watching = Having a spy report whenever something changes in a file or folder.
Watch a Single File
fs.watchFile('config.json', (curr, prev) => {
console.log('File changed!');
console.log('Old size:', prev.size);
console.log('New size:', curr.size);
});
Watch a Directory
fs.watch('./my-folder', (event, filename) => {
console.log('Event:', event);
console.log('File affected:', filename);
});
Event Types
| Event | Meaning |
|---|---|
'rename' |
File added, removed, or renamed |
'change' |
File content modified |
Stop Watching
const watcher = fs.watch('./folder', callback);
// Later, stop watching
watcher.close();
Real Life Use
- Auto-reload when code changes
- Sync files to cloud
- Trigger backups on changes
๐ File Streaming
What is it?
Streaming = Reading a book page by page instead of carrying the whole thing at once.
Why Streaming?
Imagine a book with 1 million pages. Would you:
- Carry all pages at once? ๐ต (Memory crash!)
- Read one page at a time? ๐ (Smart!)
Read Stream
const readStream = fs.createReadStream(
'bigfile.txt'
);
readStream.on('data', (chunk) => {
console.log('Got chunk:', chunk.length);
});
readStream.on('end', () => {
console.log('Done reading!');
});
Write Stream
const writeStream = fs.createWriteStream(
'output.txt'
);
writeStream.write('Hello ');
writeStream.write('World!');
writeStream.end();
Pipe: The Magic Connector
const input = fs.createReadStream('source.txt');
const output = fs.createWriteStream('copy.txt');
// Automatically handles everything!
input.pipe(output);
graph LR A["Read Stream"] -->|pipe| B["Write Stream"] A -->|chunk by chunk| B
Stream Options
const stream = fs.createReadStream('file.txt', {
encoding: 'utf8',
highWaterMark: 1024 // 1KB chunks
});
๐ฏ Quick Reference
| Task | Method |
|---|---|
| Create folder | mkdirSync(path, {recursive}) |
| List folder | readdirSync(path) |
| Delete file | unlinkSync(path) |
| Delete folder | rmSync(path, {recursive}) |
| Move file | renameSync(old, new) |
| Copy file | copyFileSync(src, dest) |
| Get info | statSync(path) |
| Check access | accessSync(path, mode) |
| Open file | openSync(path, flag) |
| Watch file | watchFile(path, callback) |
| Read stream | createReadStream(path) |
| Write stream | createWriteStream(path) |
๐ You Did It!
You now understand how Node.js manages files like a digital librarian:
- โ Create rooms (directories)
- โ See whatโs inside rooms
- โ Throw things away safely
- โ Move and copy books
- โ Read book covers (file info)
- โ Check who can access what
- โ Use library cards (file descriptors)
- โ Set up spies (watchers)
- โ Read page by page (streams)
Youโre now a File System Master! ๐
