7

I'm trying to remove node_modules directory if it exists and is not empty

var fs = require('fs'),
    path = require('path'),
    child_process = require('child_process'),
    cmd;

module.exports = function(){
    var modulesPath = '../modules';

    fs.readdirSync(modulesPath)
        .forEach(function(dir) {
            var location = path.join(dir, 'node_modules');
            if (fs.existsSync(location)){
                fs.rmdir(location);
            }
        });
};

However, fs.rmdir command unfortunately removes directory only if there are no files there.

NodeJS doesn’t have an easy way to force the removal

KyleMit
  • 30,350
  • 66
  • 462
  • 664
francesca
  • 559
  • 3
  • 10
  • 19

5 Answers5

8

A couple of things:

where does your next(err) function come from?

Also remember that rmdir in node.js documentation for the function you are calling is this: https://nodejs.org/api/fs.html#fs_fs_rmdir_path_callback

Asynchronous rmdir(2)

The posix definition of this is:

deletes a directory, which must be empty.

Make sure your directory is empty, which in this case it seems it would not be.

There is a gist here the deals with non-empty directories:

https://gist.github.com/tkihira/2367067

var fs = require("fs");
var path = require("path");

var rmdir = function(dir) {
    var list = fs.readdirSync(dir);
    for(var i = 0; i < list.length; i++) {
        var filename = path.join(dir, list[i]);
        var stat = fs.statSync(filename);

        if(filename == "." || filename == "..") {
            // pass these files
        } else if(stat.isDirectory()) {
            // rmdir recursively
            rmdir(filename);
        } else {
            // rm fiilename
            fs.unlinkSync(filename);
        }
    }
    fs.rmdirSync(dir);
};

And a node module here:

https://github.com/dreamerslab/node.rmdir

These might get you on the right track.

Jarrod
  • 163
  • 6
  • thanks! Very helpful:) find also [thread with asynchronous method](http://stackoverflow.com/questions/12627586/is-node-js-rmdir-recursive-will-it-work-on-non-empty-directories/12761924#12761924) – francesca Aug 11 '15 at 13:43
8

Two Liner:

if (fs.existsSync(dir)) {
  fs.rmdirSync(dir, {recursive: true})
}
simmer
  • 2,639
  • 1
  • 18
  • 22
nick
  • 601
  • 7
  • 7
  • 1
    Both of the functions you used are synchronous (hence Sync). The async variants can be imported from the "fs/promises" built in, although exists has been depreciated. existsSync is active but again isn't a promise. Hope this helps! – Zachary Raineri Nov 13 '20 at 01:26
  • 6
    One liner: `fs.rmSync('./dir', {force: true, recursive: true});`. [Source](https://nodejs.org/api/fs.html#fs_fs_rmsync_path_options) – kntx Sep 16 '21 at 10:16
4

Update v16 - Async & Recursive Method

You can now use fs.rm() or fs.promises.rm() like this:

fs.rm("/directory-to-delete", { recursive: true, force: true })

Options:

  • recursive <boolean> If true, perform a recursive directory removal.
  • force <boolean> If true, exceptions will be ignored if path does not exist.

Further Reading

KyleMit
  • 30,350
  • 66
  • 462
  • 664
1
var fs = require('fs');
var path = require('path');
var child_process = require('child_process');
var cmd;

module.exports = function(){
    var modulesPath = 'modules';

    fs.readdirSync(modulesPath)
        .forEach(function(dir) {
            var location = path.join(dir, 'node_modules');
            if (fs.existsSync(location)){
                fs.rmdir(location, function (err) {
                    return next(err);
                })
            }
        });
};

make sure check modules folder in current path.

  • What is `next` in this case? – Benny Code Mar 23 '17 at 13:36
  • I know this answer is a bit old, but i submitted an edit request as i think this code is supposed to be a middleware (And this is why the `next` keyword). Next is probably supposed to be from `(req, res, next)` (parameters). It would be nice if the answer has some description around it. – Alexander Santos Dec 17 '20 at 15:07
0

@since 14.4.0

const fs = require('fs')

// note `fm.rm` and `fm.rmSync` can delete files and directories
// retry options not required - might be needed if an EBUSY, EMFILE, ENFILE, ENOTEMPTY, or EPERM error is encountered
// the `force` option When true, exceptions will be ignored if path does not exist.
// the `recursive` If true, perform a recursive directory removal. In recursive mode, operations are retried on failure.

// async version - prefered - you may need to await the file deletion - works like `rm -rf`
fs.promises.rm(`<FILE|DIR_PATH>`, { maxRetries: 5, retryDelay: 2000, recursive: true, force: true })

// sync version - works like `rm -rf`
fs.rmSync(`<FILE|DIR_PATH>`, { maxRetries: 5, retryDelay: 2000, recursive: true, force: true })

Refer To:

Enogwe Victor
  • 70
  • 1
  • 5