Explain Codes LogoExplain Codes Logo

Copy folder recursively in Node.js

javascript
fs-extra
async-await
promises
Anton ShumikhinbyAnton Shumikhin·Jan 15, 2025
TLDR

To "clone" a folder and its contents in Node.js, fs-extra unveils copySync. The first move is npm install fs-extra, then power up this code:

const fs = require('fs-extra'); //Copy begins. Hold your hats! fs.copySync('/source/folder', '/destination/folder', { overwrite: true });

This code "teleports" the entire directory structure and the contents from source to destination.

For those who dance with asynchronous operations, use copy along with callbacks or grace it with async/await for a cleaner syntax:

const fs = require('fs-extra'); // Callback approach: The classic dance fs.copy('/source/folder', '/destination/folder', err => { if (err) return console.error(err); // If there's smoke, there's fire console.log('Folder copied successfully!'); // Smooth as butter }); // Async/Await approach: The suave dance async function copyFolder() { try { await fs.copy('/source/folder', '/destination/folder'); console.log('Folder copied successfully!'); // The butler did it smoothly } catch (err) { console.error(err); // No fire without smoke } } copyFolder(); // Let's get this party started!

Code begins with understanding

It's all magic until you understand it. So, let's take a little trip down the Memory Lane:

They save the day: before Node v16.7.0, copying a directory was as tiresome as finding a needle in a haystack. A cumbersome manual read/write loop. Then, here came fs.cp and fs.cpSync, playing heroes, offering a swift and native approach.

The hero's journey: introduced in Node v16.7.0, fs.cp gave the developers a tool, simple yet powerful, to copy files and directories. Do not forget to check node version requirements and the changelog to ensure compatibility and stability when using such functions – especially with features marked as experimental in certain versions, like the stability noted in Node v21.1.0.

Don’t ignore pitfalls: robust operations must dodge failures just like Neo dodges bullets in The Matrix. In asynchronous mode, loop in a callback to fs.cp to dodge such bullets. Go for try/catch with async/await when using fs-extra. Make your code dodge errors as if they are saying, "I know Kung Fu".

Efficient practices

Wrangling paths

When navigating murky waters of file paths, especially in a cross-platform environment, relish the simplicity of the path.join method. It gives you a reliable compass, giving a normalized path string:

const path = require('path'); let sourcePath = path.join('source', 'folder'); // 'source/folder' - No breadcrumbs needed let destPath = path.join('destination', 'folder'); // 'destination/folder' - Follow the path

Is anybody home?

It's like knocking before entering a room. Before creating new directories or initiating a copy operation, verify the room is empty:

const fs = require('fs-extra'); const dir = '/path/to/a/shiny/new/directory'; if (!fs.existsSync(dir)) { fs.mkdirSync(dir); // Room is empty. Let's arrange a party here }

Carry on dairy (metadata)

Everybody likes a little extra cheese, don't they? If you need to retain file attributes (like the cheese or timestamps), use fs.copyFileSync for individual files:

const fs = require('fs'); fs.copyFileSync('/source/file.txt', '/destination/file.txt'); // Stop! It's hammer time 😎

Subdirectories are just directories within directories

For custom recursive functions (prior to Node v16.7.0), you need to tell files and directories apart as smoothly as Neo sees the Matrix. Use fs.lstatSync().isDirectory() for this special vision.

Going beyond fs.cp

The extra cheese: fs-extra

fs-extra is like buying an Xbox game and getting the DLCs free. It's fs with benefits. It adds file system methods that aren't included in the vanilla module. Most importantly, it simplifies the syntax to the point it's a walk in the park:

// With fs-extra, you get extra options for extra control. Can't get any better fs.copySync('/source/folder', '/destination/folder', { overwrite: false });

Alternate routes

For those adrenaline junkies who don't mind the old-school approach, wrench.js was the answer for recursive operations. Now, it's resting in peace, with fs-extra taking up the mantle.

The Need for Speed

Brace for the impact when copying large or complex directory structures. Like a car hitting the gas, performance metrics are a good way to see if your code hits the road running.

Safety and maintenance

Stay updated

Updates are like health checkups. Stay informed about Node.js updates and adjust your code whenever newer, more efficient methods knock on your door.

Tricky little Hobbits (gotchas)

When dancing with async functions, don't step on its toes. A safe dance is a fun dance. Always have your async/await moves guarded with try/catch blocks.

Cross-platform journeys

Walking in the desert is not the same as walking in a snowstorm, same goes for running your code on different operating systems.

References