The fs Module
The fs (file system) module provides an API for interacting with the file system.
It offers both synchronous and asynchronous methods, as well as a promises-based API.
Reading Files
const fs = require('fs');
const path = require('path');
// Asynchronous (callback-based)
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log(data);
});
// Synchronous (blocks execution)
try {
const data = fs.readFileSync('example.txt', 'utf8');
console.log(data);
} catch (err) {
console.error('Error:', err);
}
// Promise-based (recommended)
const fsPromises = require('fs').promises;
async function readFile() {
try {
const data = await fsPromises.readFile('example.txt', 'utf8');
console.log(data);
} catch (err) {
console.error('Error:', err);
}
}
readFile();
Writing Files
const fs = require('fs').promises;
// Write a new file (overwrites if exists)
async function writeFile() {
await fs.writeFile('output.txt', 'Hello, Node.js!');
console.log('File written successfully');
}
// Append to a file
async function appendToFile() {
await fs.appendFile('log.txt', 'New log entry\n');
console.log('Content appended');
}
// Write JSON data
async function writeJSON() {
const data = {
name: 'John',
age: 30,
skills: ['JavaScript', 'Node.js']
};
await fs.writeFile(
'data.json',
JSON.stringify(data, null, 2) // Pretty print with 2 spaces
);
}
writeJSON();
Working with Directories
const fs = require('fs').promises;
const path = require('path');
// Create a directory
async function createDir() {
await fs.mkdir('new-folder', { recursive: true });
// recursive: true creates parent directories if needed
}
// Read directory contents
async function listFiles() {
const files = await fs.readdir('.');
console.log('Files:', files);
// With file type information
const entries = await fs.readdir('.', { withFileTypes: true });
entries.forEach(entry => {
const type = entry.isDirectory() ? 'DIR' : 'FILE';
console.log(`[${type}] ${entry.name}`);
});
}
// Remove a directory
async function removeDir() {
await fs.rmdir('old-folder', { recursive: true });
}
// Check if file/directory exists
async function checkExists(filePath) {
try {
await fs.access(filePath);
return true;
} catch {
return false;
}
}
File Information & Stats
const fs = require('fs').promises;
async function getFileInfo(filePath) {
const stats = await fs.stat(filePath);
console.log('Is file:', stats.isFile());
console.log('Is directory:', stats.isDirectory());
console.log('File size:', stats.size, 'bytes');
console.log('Created:', stats.birthtime);
console.log('Modified:', stats.mtime);
}
getFileInfo('package.json');
Copying, Moving & Deleting
const fs = require('fs').promises;
// Copy a file
async function copyFile() {
await fs.copyFile('source.txt', 'destination.txt');
}
// Rename/Move a file
async function moveFile() {
await fs.rename('old-name.txt', 'new-name.txt');
// Also works for moving to different directory
await fs.rename('file.txt', 'subfolder/file.txt');
}
// Delete a file
async function deleteFile() {
await fs.unlink('unwanted-file.txt');
}
The path Module
Use the path module for cross-platform path handling:
const path = require('path');
// Join path segments
const fullPath = path.join(__dirname, 'data', 'file.txt');
// /Users/you/project/data/file.txt
// Get file extension
console.log(path.extname('image.png')); // .png
// Get filename
console.log(path.basename('/path/to/file.txt')); // file.txt
console.log(path.basename('/path/to/file.txt', '.txt')); // file
// Get directory name
console.log(path.dirname('/path/to/file.txt')); // /path/to
// Parse path into components
const parsed = path.parse('/home/user/file.txt');
console.log(parsed);
// { root: '/', dir: '/home/user', base: 'file.txt', ext: '.txt', name: 'file' }
// Resolve to absolute path
console.log(path.resolve('data', 'file.txt'));
// /Users/you/project/data/file.txt
Practical Example: File Processor
const fs = require('fs').promises;
const path = require('path');
async function processFiles(directory) {
const entries = await fs.readdir(directory, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(directory, entry.name);
if (entry.isDirectory()) {
// Recursively process subdirectories
await processFiles(fullPath);
} else if (entry.name.endsWith('.txt')) {
// Process text files
const content = await fs.readFile(fullPath, 'utf8');
const wordCount = content.split(/\s+/).length;
console.log(`${entry.name}: ${wordCount} words`);
}
}
}
processFiles('./documents');
💡 Best Practices
- • Use the promises API (fs.promises) for cleaner async code
- • Always use path.join() for cross-platform compatibility
- • Handle errors properly with try/catch
- • Use { recursive: true } when creating nested directories
- • Consider using streams for large files