Hướng dẫn delete folder nodejs

Asked 9 years, 1 month ago

Show

Viewed 429k times

In my Node application I need to remove a directory which has some files, but fs.rmdir only works on empty directories. How can I do this?

Hướng dẫn delete folder nodejs

ZachB

11.4k2 gold badges53 silver badges87 bronze badges

asked Aug 5, 2013 at 7:31

2

As of Node.js 14.14.0, the recommended way is to use fs.rmSync:

fs.rmSync(dir, { recursive: true, force: true });

Michael Hays

2,5463 gold badges16 silver badges29 bronze badges

answered Sep 10, 2019 at 7:41

14

There is a module for this called rimraf (https://npmjs.org/package/rimraf). It provides the same functionality as rm -Rf

Async usage:

var rimraf = require("rimraf");
rimraf("/some/directory", function () { console.log("done"); });

Sync usage:

rimraf.sync("/some/directory");

answered Aug 5, 2013 at 7:43

Morgan ARR AllenMorgan ARR Allen

10.3k3 gold badges32 silver badges32 bronze badges

13

To remove folder synchronously

    const fs = require('fs');
    const Path = require('path');

    const deleteFolderRecursive = function (directoryPath) {
    if (fs.existsSync(directoryPath)) {
        fs.readdirSync(directoryPath).forEach((file, index) => {
          const curPath = path.join(directoryPath, file);
          if (fs.lstatSync(curPath).isDirectory()) {
           // recurse
            deleteFolderRecursive(curPath);
          } else {
            // delete file
            fs.unlinkSync(curPath);
          }
        });
        fs.rmdirSync(directoryPath);
      }
    };

Hướng dẫn delete folder nodejs

Abhay

2,94319 silver badges28 bronze badges

answered Aug 25, 2015 at 6:56

SharpCoderSharpCoder

17.5k42 gold badges144 silver badges239 bronze badges

18

Most of the people using fs with Node.js would like functions close to the "Unix way" of dealing with files. I'm using fs-extra to bring all the cool stuff :

fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as mkdir -p, cp -r, and rm -rf.

Even better, fs-extra is a drop in replacement for native fs. All methods in fs are unmodified and attached to it. It means that you can replace fs by fs-extra :

// this can be replaced
const fs = require('fs')

// by this
const fs = require('fs-extra')

And then you can remove a folder this way:

fs.removeSync('/tmp/myFolder'); 
//or
fs.remove('/tmp/myFolder', callback);

Hướng dẫn delete folder nodejs

answered Apr 29, 2016 at 9:13

Hướng dẫn delete folder nodejs

Pierre MaouiPierre Maoui

5,6782 gold badges26 silver badges28 bronze badges

1

As of Node v14 (October 2020), the fs module has fs.rm and rs.rmSync that support recursive, non-empty directory unlinking:

https://nodejs.org/docs/latest-v14.x/api/fs.html#fs_fs_rm_path_options_callback

So you can now do something like this:

const fs = require('fs');
fs.rm('/path/to/delete', { recursive: true }, () => console.log('done'));

or:

const fs = require('fs');
fs.rmSync('/path/to/delete', { recursive: true });
console.log('done');

Hướng dẫn delete folder nodejs

answered Jan 25, 2021 at 16:36

Hướng dẫn delete folder nodejs

1

My modified answer from @oconnecp (https://stackoverflow.com/a/25069828/3027390)

Uses path.join for better cross-platform experience. So, don't forget to require it.

var path = require('path');

Also renamed function to rimraf ;)

/**
 * Remove directory recursively
 * @param {string} dir_path
 * @see https://stackoverflow.com/a/42505874/3027390
 */
function rimraf(dir_path) {
    if (fs.existsSync(dir_path)) {
        fs.readdirSync(dir_path).forEach(function(entry) {
            var entry_path = path.join(dir_path, entry);
            if (fs.lstatSync(entry_path).isDirectory()) {
                rimraf(entry_path);
            } else {
                fs.unlinkSync(entry_path);
            }
        });
        fs.rmdirSync(dir_path);
    }
}

Hướng dẫn delete folder nodejs

Rahul Kumar

5,0305 gold badges34 silver badges44 bronze badges

answered Feb 28, 2017 at 10:13

Hướng dẫn delete folder nodejs

thybzithybzi

1,19312 silver badges15 bronze badges

I don't usually resurrect old threads but there is a lot on churn here and sans the rimraf answer these all seem overly complicated to me.

First in modern Node (>= v8.0.0) you can simplify the process using only node core modules, fully asynchronous, and parallelize the unlinking of files concurrently all in a function of five lines and still keep readability:

const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
const readdir = promisify(fs.readdir);
const rmdir = promisify(fs.rmdir);
const unlink = promisify(fs.unlink);

exports.rmdirs = async function rmdirs(dir) {
  let entries = await readdir(dir, { withFileTypes: true });
  await Promise.all(entries.map(entry => {
    let fullPath = path.join(dir, entry.name);
    return entry.isDirectory() ? rmdirs(fullPath) : unlink(fullPath);
  }));
  await rmdir(dir);
};

On another note a guard for path traversal attacks is inappropriate for this function because

  1. It is out of scope based on the Single Responsibility Principle.
  2. Should be handled by the caller not this function. This is akin to the command-line rm -rf in that it takes an argument and will allow the user to rm -rf / if asked to. It would be the responsibility of a script to guard not the rm program itself.
  3. This function would be unable to determine such an attack since it does not have a frame of reference. Again that is the responsibility of the caller who would have the context of intent which would provide it a reference to compare the path traversal.
  4. Sym-links are not a concern as .isDirectory() is false for sym-links and are unlinked not recursed into.

Last but not least, there is a rare race condition that the recursion could error if one of the entries was unlinked or deleted outside this script at just the right time while this recursion is running. Since this scenario is not typical in most environments it can likely be overlooked. However, if required (for some edge cases) this issue can be mitigated with this slightly more complex example:

exports.rmdirs = async function rmdirs(dir) {
  let entries = await readdir(dir, { withFileTypes: true });
  let results = await Promise.all(entries.map(entry => {
    let fullPath = path.join(dir, entry.name);
    let task = entry.isDirectory() ? rmdirs(fullPath) : unlink(fullPath);
    return task.catch(error => ({ error }));
  }));
  results.forEach(result => {
    // Ignore missing files/directories; bail on other errors
    if (result && result.error.code !== 'ENOENT') throw result.error;
  });
  await rmdir(dir);
};

EDIT: Make isDirectory() a function. Remove the actual directory at the end. Fix missing recursion.

answered Apr 13, 2019 at 3:51

SukimaSukima

9,8453 gold badges43 silver badges60 bronze badges

5

Here is an async version of @SharpCoder's answer

const fs = require('fs');
const path = require('path');

function deleteFile(dir, file) {
    return new Promise(function (resolve, reject) {
        var filePath = path.join(dir, file);
        fs.lstat(filePath, function (err, stats) {
            if (err) {
                return reject(err);
            }
            if (stats.isDirectory()) {
                resolve(deleteDirectory(filePath));
            } else {
                fs.unlink(filePath, function (err) {
                    if (err) {
                        return reject(err);
                    }
                    resolve();
                });
            }
        });
    });
};

function deleteDirectory(dir) {
    return new Promise(function (resolve, reject) {
        fs.access(dir, function (err) {
            if (err) {
                return reject(err);
            }
            fs.readdir(dir, function (err, files) {
                if (err) {
                    return reject(err);
                }
                Promise.all(files.map(function (file) {
                    return deleteFile(dir, file);
                })).then(function () {
                    fs.rmdir(dir, function (err) {
                        if (err) {
                            return reject(err);
                        }
                        resolve();
                    });
                }).catch(reject);
            });
        });
    });
};

answered Dec 9, 2016 at 4:06

Tony BrixTony Brix

3,9057 gold badges39 silver badges50 bronze badges

I wrote this function called remove folder. It will recursively remove all the files and folders in a location. The only package it requires is async.

var async = require('async');

function removeFolder(location, next) {
    fs.readdir(location, function (err, files) {
        async.each(files, function (file, cb) {
            file = location + '/' + file
            fs.stat(file, function (err, stat) {
                if (err) {
                    return cb(err);
                }
                if (stat.isDirectory()) {
                    removeFolder(file, cb);
                } else {
                    fs.unlink(file, function (err) {
                        if (err) {
                            return cb(err);
                        }
                        return cb();
                    })
                }
            })
        }, function (err) {
            if (err) return next(err)
            fs.rmdir(location, function (err) {
                return next(err)
            })
        })
    })
}

answered Jul 31, 2014 at 22:15

oconnecpoconnecp

7025 silver badges13 bronze badges

2

[EDIT: using node.js v15.5.0]

Having just tried using some of the solutions posted here, I encountered the following deprecation warning:

(node:13202) [DEP0147] DeprecationWarning: In future versions of Node.js, fs.rmdir(path, { recursive: true }) will throw if path does not exist or is a file. Use fs.rm(path, { recursive: true, force: true }) instead

fs.rm(path, { recursive: true, force: true }); works nicely, with fs.rmSync(path, { recursive: true, force: true }); if you want to use the blocking version.

answered Jan 23, 2021 at 13:45

therightstufftherightstuff

6571 gold badge12 silver badges16 bronze badges

4

If you are using node 8+ want asyncronicity and don't want external dependencies, here is the async/await version:

const path = require('path');
const fs = require('fs');
const util = require('util');

const readdir = util.promisify(fs.readdir);
const lstat = util.promisify(fs.lstat);
const unlink = util.promisify(fs.unlink);
const rmdir = util.promisify(fs.rmdir);

const removeDir = async (dir) => {
    try {
        const files = await readdir(dir);
        await Promise.all(files.map(async (file) => {
            try {
                const p = path.join(dir, file);
                const stat = await lstat(p);
                if (stat.isDirectory()) {
                    await removeDir(p);
                } else {
                    await unlink(p);
                    console.log(`Removed file ${p}`);
                }
            } catch (err) {
                console.error(err);
            }
        }))
        await rmdir(dir);
        console.log(`Removed dir ${dir}`);
    } catch (err) {
      console.error(err);
    }
}

answered Feb 27, 2018 at 10:39

RonZRonZ

3672 silver badges8 bronze badges

0

const fs = require("fs");
fs.rmdir("./test", { recursive: true }, (err) => {
  if (err) {
    console.error(err);
  }
});

Provide the recursive: true option. And it will recursively delete all the files and directories of the given path. (Assuming test is directory present at root. )

answered Jul 26, 2020 at 11:21

Hướng dẫn delete folder nodejs

FaiziFaizi

3296 silver badges12 bronze badges

0

From Node docs, as one can see here.

To get a behavior similar to the rm -rf Unix command, use fs.rm() with options { recursive: true, force: true }.

answered Oct 21, 2021 at 15:14

mdmundomdmundo

1,1142 gold badges19 silver badges33 bronze badges

Explanations

As of Node.js v14, we can now use the require("fs").promises.rm function to remove a file using a promise. The first argument will be the file or folder to remove (even non-existant ones). You can use the recursive and force options in the second argument's object to mimic the behavior of the rm Shell command utility with the -rf options.

Example

"use strict";

require("fs").promises.rm("directory", {recursive: true, force: true}).then(() => {
  console.log("removed");
}).catch(error => {
  console.error(error.message);
});

See

Node.js v14 Documentation

Mozilla Developer Promises Documentation

rm command manual page

answered Jun 1, 2021 at 8:06

Amin NAIRIAmin NAIRI

2,06218 silver badges19 bronze badges

I reached here while trying to get over with the gulp and I'm writing for further reaches.

  • gulp-clean deprecated for gulp-rimraf
  • gulp-rimraf deprecated in favor of delete-files-folders

When you want to delete files and folders using del, you should append /** for recursive deletion.

gulp.task('clean', function () {
    return del(['some/path/to/delete/**']);
});

answered Feb 29, 2016 at 11:21

Hướng dẫn delete folder nodejs

Jin KwonJin Kwon

18.7k12 gold badges102 silver badges165 bronze badges

Async version of @SharpCoder's answer using fs.promises:

const fs = require('fs');
const afs = fs.promises;

const deleteFolderRecursive = async path =>  {
    if (fs.existsSync(path)) {
        for (let entry of await afs.readdir(path)) {
            const curPath = path + "/" + entry;
            if ((await afs.lstat(curPath)).isDirectory())
                await deleteFolderRecursive(curPath);
            else await afs.unlink(curPath);
        }
        await afs.rmdir(path);
    }
};

answered Jul 25, 2018 at 13:58

Error404Error404

71110 silver badges28 bronze badges

2020 Update

From version 12.10.0 recursiveOption has been added for options.

Note that recursive deletion is experimental.

So you would do for sync:

fs.rmdirSync(dir, {recursive: true});

or for async:

fs.rmdir(dir, {recursive: true});

answered Jan 2, 2020 at 20:04

Hướng dẫn delete folder nodejs

According to the fs documentation, fsPromises currently provides the recursive option on an experimental basis, which, at least in my own case on Windows, removes the directory and any files therein.

fsPromises.rmdir(path, {
  recursive: true
})

Does recursive: true remove the files on Linux and MacOS?

answered Feb 11, 2020 at 2:53

Hướng dẫn delete folder nodejs

oldboyoldboy

5,2744 gold badges26 silver badges74 bronze badges

1

return new Promise((resolve, reject) => {
  const fs = require("fs");
  // directory path
  const dir = "your/dir";

  // delete directory recursively <------
  fs.rmdir(dir, { recursive: true }, (err) => {
    if (err) {
      reject(err);
    }
    resolve(`${dir} is deleted!`);
  });
});

answered Nov 15, 2020 at 17:26

Just use rmdir module! it's easy and simple.

answered Sep 14, 2015 at 11:23

Hướng dẫn delete folder nodejs

AminovskiAminovski

1451 silver badge5 bronze badges

2

A quick and dirty way (maybe for testing) could be to directly use the exec or spawn method to invoke OS call to remove the directory. Read more on NodeJs child_process.

let exec = require('child_process').exec
exec('rm -Rf /tmp/*.zip', callback)

Downsides are:

  1. You are depending on underlying OS i.e. the same method would run in unix/linux but probably not in windows.
  2. You cannot hijack the process on conditions or errors. You just give the task to underlying OS and wait for the exit code to be returned.

Benefits:

  1. These processes can run asynchronously.
  2. You can listen for the output/error of the command, hence command output is not lost. If operation is not completed, you can check the error code and retry.

answered Feb 26, 2018 at 3:29

RashRash

7,2371 gold badge49 silver badges71 bronze badges

2

The de facto package is rimraf, but here is my tiny async version:

const fs = require('fs')
const path = require('path')
const Q = require('q')

function rmdir (dir) {
  return Q.nfcall(fs.access, dir, fs.constants.W_OK)
    .then(() => {
      return Q.nfcall(fs.readdir, dir)
        .then(files => files.reduce((pre, f) => pre.then(() => {
          var sub = path.join(dir, f)
          return Q.nfcall(fs.lstat, sub).then(stat => {
            if (stat.isDirectory()) return rmdir(sub)
            return Q.nfcall(fs.unlink, sub)
          })
        }), Q()))
    })
    .then(() => Q.nfcall(fs.rmdir, dir))
}

answered Dec 21, 2017 at 14:27

Hướng dẫn delete folder nodejs

clarkttfuclarkttfu

5275 silver badges9 bronze badges

Ultra-speed and fail-proof

You can use the lignator package (https://www.npmjs.com/package/lignator), it's faster than any async code (e.g. rimraf) and more fail-proof (especially in Windows, where file removal is not instantaneous and files might be locked by other processes).

4,36 GB of data, 28 042 files, 4 217 folders on Windows removed in 15 seconds vs rimraf's 60 seconds on old HDD.

const lignator = require('lignator');

lignator.remove('./build/');

answered Aug 3, 2019 at 17:09

Hướng dẫn delete folder nodejs

HankMoodyHankMoody

3,0091 gold badge16 silver badges35 bronze badges

Sync folder remove with the files or only a file.

I am not much of a giver nor a contributor but I couldn't find a good solution of this problem and I had to find my way... so I hope you'll like it :)

Works perfect for me with any number of nested directories and sub directories. Caution for the scope of 'this' when recursing the function, your implementation may be different. In my case this function stays into the return of another function that's why I am calling it with this.

    const fs = require('fs');

    deleteFileOrDir(path, pathTemp = false){
            if (fs.existsSync(path)) {
                if (fs.lstatSync(path).isDirectory()) {
                    var files = fs.readdirSync(path);
                    if (!files.length) return fs.rmdirSync(path);
                    for (var file in files) {
                        var currentPath = path + "/" + files[file];
                        if (!fs.existsSync(currentPath)) continue;
                        if (fs.lstatSync(currentPath).isFile()) {
                            fs.unlinkSync(currentPath);
                            continue;
                        }
                        if (fs.lstatSync(currentPath).isDirectory() && !fs.readdirSync(currentPath).length) {
                            fs.rmdirSync(currentPath);
                        } else {
                            this.deleteFileOrDir(currentPath, path);
                        }
                    }
                    this.deleteFileOrDir(path);
                } else {
                    fs.unlinkSync(path);
                }
            }
            if (pathTemp) this.deleteFileOrDir(pathTemp);
        }

answered Aug 7, 2019 at 6:44

MetaTronMetaTron

6956 silver badges11 bronze badges

2020 Answer

If you want to do it in a npm script, You DON'T need to previously install any 3rd party package if you use the command npx

If for example, you want to delete the folders dist and .cache when you run npm run clean then just add this command to your package.json

{
  "scripts": {
    "clean": "npx rimraf dist .cache"
  }
}

It will work in any operative system

answered Nov 22, 2020 at 1:53

Juanma MenendezJuanma Menendez

14.2k7 gold badges53 silver badges47 bronze badges

5

In an asynchronous approach , to delete a non empty dir using the

rmdir(path,{recursive:true,force:true}
rm(path,{recursive:true,force:true}

will work

A code snippet:

const fsp = require("fs/promises");

deleteDirRecursively("./b");
removeRecursively("./BCD/b+");

async function deleteDirRecursively(dirPath) {
  try {
    // fsPromises.rmdir() on a file (not a directory) results in the promise being rejected
    // with an ENOENT error on Windows and an ENOTDIR error on POSIX.
    // To get a behavior similar to the rm -rf Unix command,
    // use fsPromises.rm() with options { recursive: true, force: true }.
    //will not thorw error if dir is empty
    //will thow error if dir is not present
    await fsp.rmdir(dirPath, { recursive: true, force: true });
    console.log(dirPath, "deleted successfully");
  } catch (err) {
    console.log(err);
  }

async function removeRecursively(path) {
  try {
    //has ability to remove both file and dir
    //can delete dir recursively and forcefully
    //will delete an empty dir.
    //will remove all the contents of a dir.
    // the only difference between rmdir and rm is that rmdir can only delete dir's
    await fsp.rm(path, { recursive: true, force: true });
    console.log(path, "deleted successfully");
  } catch (err) {
    console.log(err);
  }
}

answered Aug 24 at 3:57

Hướng dẫn delete folder nodejs

Another alternative is using the fs-promise module that provides promisified versions of the fs-extra modules

you could then write like this example:

const { remove, mkdirp, writeFile, readFile } = require('fs-promise')
const { join, dirname } = require('path')

async function createAndRemove() {
  const content = 'Hello World!'
  const root = join(__dirname, 'foo')
  const file = join(root, 'bar', 'baz', 'hello.txt')

  await mkdirp(dirname(file))
  await writeFile(file, content)
  console.log(await readFile(file, 'utf-8'))
  await remove(join(__dirname, 'foo'))
}

createAndRemove().catch(console.error)

note: async/await requires a recent nodejs version (7.6+)

answered Mar 30, 2017 at 14:16

Max FichtelmannMax Fichtelmann

3,2361 gold badge20 silver badges27 bronze badges

I wish there was a way to do this without additional modules for something so minuscule and common, but this is the best I could come up with.

Update: Should now work on Windows (tested Windows 10), and should also work on Linux/Unix/BSD/Mac systems.

const
    execSync = require("child_process").execSync,
    fs = require("fs"),
    os = require("os");

let removeDirCmd, theDir;

removeDirCmd = os.platform() === 'win32' ? "rmdir /s /q " : "rm -rf ";

theDir = __dirname + "/../web-ui/css/";

// WARNING: Do not specify a single file as the windows rmdir command will error.
if (fs.existsSync(theDir)) {
    console.log(' removing the ' + theDir + ' directory.');
    execSync(removeDirCmd + '"' + theDir + '"', function (err) {
        console.log(err);
    });
}

answered Sep 4, 2016 at 12:35

b01b01

3,8421 gold badge28 silver badges28 bronze badges

5

This is one approach using promisify and two help functions (to and toAll) to resolve the promise.

It does all actions asynchrounous.

const fs = require('fs');
const { promisify } = require('util');
const to = require('./to');
const toAll = require('./toAll');

const readDirAsync = promisify(fs.readdir);
const rmDirAsync = promisify(fs.rmdir);
const unlinkAsync = promisify(fs.unlink);

/**
    * @author Aécio Levy
    * @function removeDirWithFiles
    * @usage: remove dir with files
    * @param {String} path
    */
const removeDirWithFiles = async path => {
    try {
        const file = readDirAsync(path);
        const [error, files] = await to(file);
        if (error) {
            throw new Error(error)
        }
        const arrayUnlink = files.map((fileName) => {
            return unlinkAsync(`${path}/${fileName}`);
        });
        const [errorUnlink, filesUnlink] = await toAll(arrayUnlink);
        if (errorUnlink) {
            throw new Error(errorUnlink);
        }
        const deleteDir = rmDirAsync(path);
        const [errorDelete, result] = await to(deleteDir);
        if (errorDelete) {
            throw new Error(errorDelete);
        }
    } catch (err) {
        console.log(err)
    }
}; 

answered Oct 22, 2018 at 14:18

Hướng dẫn delete folder nodejs

Aecio LevyAecio Levy

1291 silver badge8 bronze badges