Ist node.js rmdir rekursiv? Funktioniert es in nicht leeren Verzeichnissen?


76

Die Dokumentation für fs.rmdir ist sehr kurz und erklärt nicht das Verhalten von rmdir, wenn das Verzeichnis nicht leer ist.

F : Was passiert, wenn ich versuche, mit dieser API ein nicht leeres Verzeichnis zu löschen?


10
Was ist passiert, als du es versucht hast?
Beny23

11
@ beny23 Siehe meine Antwort; =). Dies ist nur ein Frage / Antwort-Paar, um Wissen zu teilen. Wenn also das nächste Mal jemand "nodejs rmdir non-empty directory" googelt, findet er die Antwort. Sie können SO dafür verwenden, wenn Sie eine Frage untersuchen müssen, welche Antwort andere Menschen interessieren könnte
Samuel Rossille

Dies ist nur ein Beispiel für ein allgemeines Problem. Node.js stützt sich stark auf die darunter liegende Posix-Ebene (und das ist darin nicht eindeutig). Daher sollte diese Frage kein Präzedenzfall für Leute werden, die nach ähnlichen Unix-Funktionen fragen, die in node.js (oder ruby ​​oder ...) eingeschlossen sind. Können wir also die Frage zu etwas Allgemeinerem verbessern und dabei rmdir als konkretes Beispiel beibehalten?
Henk Langeveld

Beantwortet das deine Frage? Entfernen Sie das nicht leere
Verzeichnis

Antworten:


37

Kurze Antwort: node.js fs.rmdir() ruft den POSIX auf rmdir(); Dadurch wird ein leeres Verzeichnis entfernt oder ein Fehler zurückgegeben . Im gegebenen Fall ruft der Aufruf die Rückruffunktion auf und übergibt den Fehler als Ausnahme.

Das Problem hierbei ist, dass sich die Dokumentation zu node.js auf POSIX bezieht :

Die Node.js API Docs File System API wurde als gestartet

einfache Wrapper um Standard-POSIX-Funktionen.

Dies verwandelt die Frage fast in ein Duplikat von: Gibt es eine Auflistung der POSIX-API / -Funktionen?

Die Beschreibung für fs.rmdirist knapp, aber ausreichend.

Asynchrones rmdir (2).

Das rmdir(2)hier ist ein impliziter Verweis auf die Dokumentation für das rmdir() system call. Die Nummer (2) hier ist eine alte Unix-Manpage-Konvention, die Abschnitt 2 der Handbuchseiten angibt, der die Kernel-Schnittstellen enthält.


75
aber wie WÜRDEN wir ein nicht leeres Verzeichnis löschen?
Markasoftware

7
@Markasoftware - Das war außerhalb des Rahmens der ursprünglichen Frage, aber einige andere Antworten hier verweisen auf rimraf . Schau sie dir an.
Henk Langeveld

4
Sie können jetzt einen Parameter verwenden, um rmdirrekursiv aufzurufen

1
Das rekursive Entfernen ist experimentell ab Knoten v13.0.1
Tim

96

Obwohl ich für so etwas eine Bibliothek eines Drittanbieters verwende, könnte ich keine elegantere Lösung finden. Also habe ich das npm-Modul rimraf benutzt .

Es installieren

npm install rimraf

Oder installieren Sie es und speichern Sie es in 'package.json' (weitere Speicheroptionen finden Sie in den npm-Installationsdokumenten ).

npm install --save rimraf

Dann können Sie Folgendes tun:

rmdir = require('rimraf');
rmdir('some/directory/with/files', function(error){});

Oder in Coffeescript:

rmdir = require 'rimraf'
rmdir 'some/directory/with/files', (error)->

6
Es gibt keine Notwendigkeit für require('./node_modules/rimraf');- Sie könnten nurrequire('rimraf');
surui

1
Wenn ich dies als Teil einer Cakefile unter Windows (unter Git Bash) ausführe, wird der Fehlerrückruf aufgerufen, jedoch mit einem Nullargumentwert, jedoch scheinen die angegebenen Verzeichnisse korrekt gelöscht zu werden. Ist das beabsichtigt?
Dai

1
rimraf wird auf den Kern von Node.j portiert und fs.rmdirunterstützt die recursiveOption seit Node.js v12.10.0. Siehe meine Antwort .
Kimamula

56

Ich habe genau über dieses Problem geschrieben .

Meine vorherige Lösung unten ist zwar einfach, wird aber nicht bevorzugt. Die folgende Funktion ist eine synchrone Lösung. während Async bevorzugt werden könnte.

deleteFolderRecursive = function(path) {
    var files = [];
    if( fs.existsSync(path) ) {
        files = fs.readdirSync(path);
        files.forEach(function(file,index){
            var curPath = path + "/" + file;
            if(fs.lstatSync(curPath).isDirectory()) { // recurse
                deleteFolderRecursive(curPath);
            } else { // delete file
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(path);
    }
};

[Bearbeiten] lstat anstelle von stat hinzugefügt, um Fehler bei Symlinks zu vermeiden

[Vorherige Lösung]

Meine Lösung hierfür ist recht einfach zu implementieren.

var exec = require('child_process').exec,child;
child = exec('rm -rf test',function(err,out) { 
  console.log(out); err && console.log(err); 
});

Dies ist für diese Seite abgespeckt, aber die Grundidee ist einfach; Führen Sie 'rm -r' in der Befehlszeile aus. Wenn Ihre App auf verschiedenen Betriebssystemtypen ausgeführt werden muss, fügen Sie dies in eine Funktion ein und verfügen Sie über einen if / else / -Schalter, um damit umzugehen.

Sie möchten alle Antworten verarbeiten. aber die Idee ist einfach genug.


2
Das ist keine gute Idee. Es gibt fs.rmdirund es wird auch unter Windows nicht funktionieren.
Nalply

8
Dies ist eine schlechte Idee: Sie verlieren die Portabilität, und außerdem ist das Hacken mit nativen ausführbaren Dateien immer gefährlicher und sensibler als die Verwendung der APIs Ihrer Sprache.
Samuel Rossille

1
Ich habe eine weitere Lösung hinzugefügt, die einen synchronen Weg zur Ausführung dieser Aufgabe zeigt.
Geedew

1
@PineappleUndertheSea - Das liegt daran, dass das Beispiel verwendet wurde, stat()als es hätte verwendet werden sollen lstat(), was auch bedeutet, dass es dem Link folgte und den Inhalt des Zielverzeichnisses löschte, bevor es fehlerhaft wurde! Eek! Ich schlug eine Änderung vor, um sie zu ändern lstat.
Kenton Varda

2
Verwenden Sie path.join(path, file)anstelle vonpath + "/" + file
Ludohen

19

Node.js v12.10.0 hat die recursiveOption in eingeführt fs.rmdir. Da fs.mkdirdieselbe Option seit Version 10.12.0 unterstützt wird, können das Erstellen und Entfernen von Verzeichnissen rekursiv ausgeführt werden.

$ node --experimental-repl-await

# without recursive option -> error
> await fs.promises.mkdir('foo/bar')
Thrown:
[Error: ENOENT: no such file or directory, mkdir 'foo/bar'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'mkdir',
  path: 'foo/bar'
}

# with recursive option -> success
> await fs.promises.mkdir('foo/bar', { recursive: true })
undefined

# without recursive option -> error
> await fs.promises.rmdir('foo')
Thrown:
[Error: ENOTEMPTY: directory not empty, rmdir 'foo'] {
  errno: -66,
  code: 'ENOTEMPTY',
  syscall: 'rmdir',
  path: 'foo'
}

# with recursive option -> success
> await fs.promises.rmdir('foo', { recursive: true })
undefined

Ich habe dies durch Überprüfen der Versionshinweise für v12.10.0 bestätigt. nodejs.org/en/blog/release/v12.10.0
Edmond Weiss

Vor Version 12.10.0 war die ausgewählte Antwort die beste Option. @Kimamula ist jedoch korrekt. Jeder, der mit der LTS- oder der aktuellen Version von Node.js arbeitet, sollte auf diese Antwort achten. (Einige Jahre später meine Stimme hier neu
formulieren

7

Nur ein kleiner Punkt unter diesen Antworten, aber ich denke, es ist gut, darauf hinzuweisen.

Persönlich (und allgemein) würde ich es vorziehen, eine bereits vorhandene Bibliothek, falls verfügbar, für die Ausführung der Aufgabe zu verwenden. Eine bereits existierende Sache zu nehmen bedeutet für mich und insbesondere in der Open Source-Welt, eine bereits existierende Sache zu nutzen und zu verbessern, was zu einem besseren Ergebnis führen könnte, als es alleine zu tun (ich verbessere etwas, das jemand anderes hat erledigt).

In diesem Fall fand ich mit einer kleinen Suche das Modul fs-extra heraus , das auch als Ersatz für rimrafdie Notwendigkeit dienen soll, rekursiv Verzeichnisse zu entfernen (anscheinend mit asynchronen und synchronisierten Versionen). Darüber hinaus hat es eine gute Anzahl von Sternen auf Github und scheint derzeit erhalten zu sein: Diese beiden Bedingungen, zusätzlich zu der Tatsache, dass Antworten auf die Bedürfnisse, machen es für mich zum richtigen Weg (fast für ein bisschen).


3
fs-extra ist kein Ersatz für rimraf, es enthält rimraf. Unabhängig davon denke ich, dass fs-extra eine gute Idee ist, und ich werde es in meinem Projekt verwenden.
Bryan Larsen

In ähnlicher Weise gibt es auch fs-tools.
Bryan Larsen

5

fs.rmdirist nicht rekursiv.

Sie können stattdessen ein rekursives fs.readdir-Modul wie readdirp verwenden, um alle Dateien und Verzeichnisse zu finden. Entfernen Sie dann alle Dateien, gefolgt von allen Verzeichnissen.

Für eine noch einfachere Lösung schauen Sie sich rimraf an .


3

Verwenden Sie child_process.execFile, es ist schneller .

NodeJS-Dokumente:

child_process.execFile ähnelt child_process.exec (), außer dass * keine Subshell ausgeführt wird, sondern die angegebene Datei direkt.

Das funktioniert. Nachahmungrm -rf DIR...

var child = require('child_process');

var rmdir = function(directories, callback) {
    if(typeof directories === 'string') {
        directories = [directories];
    }
    var args = directories;
    args.unshift('-rf');
    child.execFile('rm', args, {env:process.env}, function(err, stdout, stderr) {
            callback.apply(this, arguments);
    });
};

// USAGE
rmdir('dir');
rmdir('./dir');
rmdir('dir/*');
rmdir(['dir1', 'dir2']);

Bearbeiten : Ich muss zugeben, dass dies nicht plattformübergreifend ist, funktioniert nicht unter Windows


3

Das hat bei mir funktioniert

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

2

Hier ist eine asynchrone rekursive Version, die mit Versprechungen arbeitet. Ich benutze die 'Q'-Bibliothek, aber jeder wird ein paar Änderungen vornehmen (zB die' Fail'-Funktion).

Um davon Gebrauch zu machen, müssen wir einige einfache Wrapper um einige Kernknotenfunktionen erstellen, nämlich fs.stat, fs.readdir, fs.unlink und fs.rmdir, um sie vielversprechend zu machen.

Hier sind sie:

function getStat(fpath) {
  var def = Q.defer();
  fs.stat(fpath, function(e, stat{
    if (e) { def.reject(); } else { def.resolve(stat); }
  });
  return def.promise;
}

function readdir(dirpath) {
  var def = Q.defer();
  fs.readdir(dirpath, function(e, files) {
    if (e) { def.reject(e); } else { def.resolve(files); }
  });
  return def.promise;
}

function rmFile(fpath) {
  var def = Q.defer();
  fs.unlink(fpath, function(e) { if(e) { def.reject(e); } else { def.resolve(fpath); }});
  return def.promise;
}

function rmDir(fpath) {
  var def = Q.defer(); 
  fs.rmdir(fpath, function(e) { if(e) { def.reject(e); } else { def.resolve(fpath); }});
  return def.promise;
}

Hier ist also die rekursive rm-Funktion:

var path = require('path');

function recursiveDelete(fpath) {
  var def = Q.defer();

  getStat(fpath)
  .then(function(stat{
    if (stat.isDirectory()) {
      return readdir(fpath)
      .then(function(files) {
        if (!files.length) { 
          return rmDir(fpath);
        } else {
          return Q.all(files.map(function(f) { return recursiveDelete(path.join(fpath, f)); }))
          .then(function() return rmDir(fpath); });
        }
      }); 
    } else {
      return rmFile(fpath);
    }
  })
  .then(function(res) { def.resolve(res); })
  .fail(function(e) { def.reject(e); })
  .done();
  return def.promise;
}

Ich habe eine ähnliche Lösung auch mit Q geschrieben :) Ich mag deine auch. Wird die Datei files.length benötigt? In meiner Lösung überprüfe ich es nicht und es löscht den Ordner richtig. Sie finden meinen Code her: gist.github.com/Sharian/067d1f572d1a00655e5a
TOAOGG

warum nicht Q.ninvoke(fs, "rmdir"...)?
Imskull

1

Ich dachte, das wäre eine gute Ausrede, um in die Quelle einzutauchen;)

fs.rmdirSoweit ich das beurteilen kann, ist die Funktion rmdir von unistd.h an gebunden. Aus der POSIX-Manpage für rmdir :

Die Funktion rmdir () entfernt ein Verzeichnis, dessen Name durch den Pfad angegeben wird. Das Verzeichnis darf nur entfernt werden, wenn es sich um ein leeres Verzeichnis handelt.

Wenn das Verzeichnis kein leeres Verzeichnis ist, schlägt rmdir () fehl und setzt errno auf [EEXIST] oder [ENOTEMPTY].



1

Mir ist klar, dass dies die vorliegende Frage nicht genau beantwortet, aber ich denke, dass dies für jemanden nützlich sein könnte, der hier in Zukunft sucht (es wäre für mich gewesen!): Ich habe einen kleinen Ausschnitt erstellt, mit dem man rekursiv nur leere löschen kann Verzeichnisse . Wenn ein Verzeichnis (oder eines seiner untergeordneten Verzeichnisse) Inhalt enthält, wird es in Ruhe gelassen:

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

var rmdir = function(dir) {
    var empty = true, list = fs.readdirSync(dir);
    for(var i = list.length - 1; i >= 0; i--) {
        var filename = path.join(dir, list[i]);
        var stat = fs.statSync(filename);

        if(filename.indexOf('.') > -1) {
            //There are files in the directory - we can't empty it!
            empty = false;
            list.splice(i, 1);
        }
    }

    //Cycle through the list of sub-directories, cleaning each as we go
    for(var i = list.length - 1; i >= 0; i--) {
        filename = path.join(dir, list[i]);
        if (rmdir(filename)) {
            list.splice(i, 1);
        }
    }

    //Check if the directory was truly empty
    if (!list.length && empty) {
        console.log('delete!');
        fs.rmdirSync(dir);
        return true;
    }
    return false;
};

https://gist.github.com/azaslavsky/661020d437fa199e95ab



0

Diese Funktion löscht rekursiv ein Verzeichnis oder eine Datei, die Sie angeben, synchron:

var path = require('path');

function deleteRecursiveSync(itemPath) {
    if (fs.statSync(itemPath).isDirectory()) {
        _.each(fs.readdirSync(itemPath), function(childItemName) {
            deleteRecursiveSync(path.join(itemPath, childItemName));
        });
        fs.rmdirSync(itemPath);
    } else {
        fs.unlinkSync(itemPath);
    }
}

Ich habe das Verhalten dieser Funktion nicht getestet, wenn:

  • der Artikel existiert nicht oder
  • Das Element kann nicht gelöscht werden (z. B. aufgrund eines Berechtigungsproblems).

0

Rekursives Verzeichnis zum Entfernen für Node.js.

Es stellte sich heraus, dass das Node.js fs-Modul keine Methode zum rekursiven Entfernen des Verzeichnisses und seines Inhalts hat. Stattdessen sollten Sie die Verzeichnisstruktur durchgehen und atomare Elemente entfernen, dh einzelne Dateien und leere Verzeichnisse. Also fand ich eine nette Zusammenfassung von Takuo Kihira unter https://gist.github.com/2367067, die in JavaScript erstellt wurde, und entschied mich , eine CoffeeScript-Version davon zu erstellen :


0

Es wurde versucht, die Ausfallsicherheit zu gewährleisten, da das Entfernen der Synchronisierung zu Fehlern führt, wenn zu diesem Zeitpunkt Datei oder Verzeichnis verwendet werden.

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

var dumpDirs = function (dir, name, cb) {
fs.readdir(dir, function (err, files) {
    var dirs = [],
    filePath, i = 0, l = files.length;
    for (var i = 0; i < l; i++) {
        filePath = path.join(dir, files[i]);
        var stats = fs.lstatSync(filePath);
        if (stats.isDirectory()) {
            if (files[i].indexOf(name) != -1) {
                dirs.push({
                    startOn: new Date(stats.ctime),
                    instance: files[i],
                    name: name
                })
            }
        }
    }
    cb(dirs);
});
}

var removeDir = function (dir, callback) {
fs.readdir(dir, function (err, files) {
    c = files.length;

    (function remfile(i, cb) {
        if (i >= c)
            return cb();
        var p = path.join(dir, files[i])
        fs.unlink(p, function (err) {
            if (err) console.log(err);
            remfile(i + 1, cb)
        });

    })(0, function () {
        fs.rmdir(dir, function (err) {
            callback()
        });
    });

    //for (var i = 0; i < c; i++) {
    //    fs.unlinkSync(path.join(dir, files[i]));
    //};


});
}
dumpDirs(maindir, function (dirs) {

if (dirs && dirs.length > 0) {
    (function rem(i, cb) {
        if (i >= dirs.length) {
            return cb();
        }
        var folder = path.join(dump, dirs[i].instance);
        removeDir(folder, function () {
            rem(i + 1, cb);
        });
    })(0, function () {
        callback();
    })
}
else {
    callback();
}
});

0

Hier ist die Prototypfunktion des Kaffeeskripts , die ich für fluentnode erstellt habe und die einen Ordner rekursiv löscht

String::folder_Delete_Recursive = ->
  path = @.toString()
  if path.exists()
    for file in path.files()
      curPath = path.path_Combine(file)
      if curPath.is_Folder()
        curPath.folder_Delete_Recursive()
      else
        curPath.file_Delete()
    fs.rmdirSync(path);

  return path.not_Exists()

Hier ist der Test:

it 'folder_Create and folder_Delete' , ->
  tmpDir = "./".temp_Name_In_Folder()
  expect(tmpDir.folder_Exists()).to.be.false
  expect(tmpDir.folder_Create()).to.equal(tmpDir.realPath())
  expect(tmpDir.folder_Exists()).to.be.true
  expect(tmpDir.folder_Delete()).to.be.true
  expect(tmpDir.folder_Exists()).to.be.false

it 'folder_Delete_Recursive' , ->
  tmpDir = "./"   .temp_Name_In_Folder().folder_Create()
  tmpFile = tmpDir.temp_Name_In_Folder().file_Create()
  expect(tmpDir.folder_Delete_Recursive()).to.be.true

0

Eine ordentliche synchrone Version von rmdirSync.

/** 
 * use with try ... catch ...
 * 
 * If you have permission to remove all file/dir
 * and no race condition and no IO exception...
 * then this should work 
 *
 * uncomment the line 
 *   if(!fs.exists(p)) return 
 * if you care the inital value of dir, 
 * 
 */
var fs = require('fs')
var path = require('path')

function rmdirSync(dir,file){
  var p = file? path.join(dir,file):dir;
  // if(!fs.exists(p)) return 
  if(fs.lstatSync(p).isDirectory()){
    fs.readdirSync(p).forEach(rmdirSync.bind(null,p))
    fs.rmdirSync(p)
  }
  else fs.unlinkSync(p)
}

Und eine parallele asynchrone E / A-Version von rmdir. (schneller)

/**
 * NOTE: 
 * 
 * If there are no error, callback will only be called once.
 * 
 * If there are multiple errors, callback will be called 
 * exactly as many time as errors occur. 
 * 
 * Sometimes, this behavior maybe useful, but users 
 * should be aware of this and handle errors in callback. 
 * 
 */

var fs = require('fs')
var path = require('path')

function rmfile(dir, file, callback){
  var p = path.join(dir, file)
  fs.lstat(p, function(err, stat){
    if(err) callback.call(null,err)
    else if(stat.isDirectory()) rmdir(p, callback)
    else fs.unlink(p, callback)
  })
}

function rmdir(dir, callback){
  fs.readdir(dir, function(err,files){
    if(err) callback.call(null,err)
    else if( files.length ){
      var i,j
      for(i=j=files.length; i--; ){
        rmfile(dir,files[i], function(err){
          if(err) callback.call(null, err)
          else if(--j === 0 ) fs.rmdir(dir,callback)
        })
      }
    }
    else fs.rmdir(dir, callback)
  })
}

Auf jeden Fall, wenn Sie eine sequentielle E / A wünschen und der Rückruf genau einmal aufgerufen werden soll (entweder erfolgreich oder mit dem ersten aufgetretenen Fehler). Ersetzen Sie dieses rmdir durch das oben genannte. (Langsamer)

function rmdir(dir, callback){
  fs.readdir(dir, function(err,files){
    if(err) callback.call(null,err)
    else if( files.length ) rmfile(dir, files[0], function(err){
      if(err) callback.call(null,err)
      else rmdir(dir, callback)
    })
    else fs.rmdir(dir, callback)
  })
}

Alle von ihnen hängen NUR von node.js ab und sollten portabel sein.


0

Dieser Beitrag erhielt die beste Antwort von Google, aber keine der Antworten bietet eine Lösung, die:

  • nutzt keine Synchronisierungsfunktionen

  • benötigt keine externen Bibliotheken

  • verwendet bash nicht direkt

Hier ist meine asyncLösung, die nichts anderes als den installierten Knoten voraussetzt:

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

function rm(path){  
    return stat(path).then((_stat) => {                                   

    if(_stat.isDirectory()){                                                                                                                                                                                                                          
      return ls(path)                                                                                                                                                                                                                                   
        .then((files) => Promise.all(files.map(file => rm(Path.join(path, file)))))
       .then(() => removeEmptyFolder(path));                                                                                                                                                                                                 
    }else{                                                                                                                                                                                                                                            
      return removeFileOrLink(path);                                                                                                                                                                                                            
    }   });
                                                                                                                                                                                                                                              function removeEmptyFolder(path){                                     

    return new Promise((done, err) => {                                                                                                                                                                                                               
      fs.rmdir(path, function(error){                                                                                                                                                                                                                   
        if(error){ return err(error); }                                                                                                                                                                                                               
        return done("ok");                                                                                                                                                                                                                        
      });                                                                                                                                                                                                                                       
    });                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                function removeFileOrLink(path){                                      

    return new Promise((done, err) => {                                                                                                                                                                                                               
      fs.unlink(path, function(error){                                                                                                                                                                                                                  
        if(error){ return err(error); }                                                                                                                                                                                                               
        return done("ok");                                                                                                                                                                                                                        
      });                                                                                                                                                                                                                                       
    });                                                                                                                                                                                                                                          }

                                                                                                                                                                                                                                                function ls(path){                                                    

    return new Promise((done, err) => {                                                                                                                                                                                                               
      fs.readdir(path, function (error, files) {                                                                                                                                                                                                        
        if(error) return err(error)                                                                                                                                                                                                                   
        return done(files)                                                                                                                                                                                                                        
      });                                                                                                                                                                                                                                       
    });                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                function stat(path){                                                  

    return new Promise((done, err) => {                                                                                                                                                                                                               
      fs.stat(path, function (error, _stat) {                                                                                                                                                                                                           
        if(error){ return err(error); }                                                                                                                                                                                                               
        return done(_stat);                                                                                                                                                                                                                       
      });                                                                                                                                                                                                                                       
    });                                                                                                                                                                                                                                          } }

0

Folgen Sie der Antwort von @ geedew.

Hier ist eine asynchrone Implementierung von rm -r(dh Sie können einen Pfad zu einer Datei oder einem Verzeichnis übergeben). Ich bin kein erfahrener NodeJS-Entwickler und freue mich über Vorschläge oder konstruktive Kritik.

var fs = require('fs');

function ResultsCollector (numResultsExpected, runWhenDone) {
    this.numResultsExpected = numResultsExpected,
    this.runWhenDone = runWhenDone;
    this.numResults = 0;
    this.errors = [];

    this.report = function (err) {
        if (err) this.errors.push(err);
        this.numResults++;
        if (this.numResults == this.numResultsExpected) {
            if (this.errors.length > 0) return runWhenDone(this.errors);
            else return runWhenDone();
        }
    };
}

function rmRasync(path, cb) {
    fs.lstat(path, function(err, stats) {
        if (err && err.code == 'ENOENT') return cb(); // doesn't exist, nothing to do
        else if (err) {
            return cb(err);
        }
        if (stats.isDirectory()) {
            fs.readdir(path, function (err, files) {
                if (err) return cb(err);
                var resultsCollector = new ResultsCollector(files.length, function (err) {
                    if (err) return cb(err);
                    fs.rmdir(path, function (err) {
                        if (err) return cb(err);
                        return cb();
                    });
                });
                files.forEach(function (file) {
                    var filePath = path + '/' + file;
                    return rmRasync(filePath, function (err) {
                        return resultsCollector.report(err);
                    });
                });
            });
        }
        else { // file.
            // delete file or link
            fs.unlink(path, function (err) {
                if (err) return cb(err);
                return cb();
            });
        }
    });
};

Rufen Sie so auf:

rmRasync('/path/to/some/file/or/dir', function (err) {
    if (err) return console.error('Could not rm', err);
    // else success
});

-1

Überraschend ausführliche und schlechte Antworten hier ...

So löschen Sie ein nicht leeres Verzeichnis auf den meisten Systemen:

import * as cp from 'child_process';

const dir = '/the/dir/to/remove';

const k = cp.spawn('bash');

k.stdin.end(`rm -rf "${dir}"`);

k.once('exit', code => {
   // check the exit code
   // now you are done
});

Dies funktioniert unter MacOS und Linux, unter einigen Windows-Betriebssystemen jedoch möglicherweise nicht.


Bitte tun Sie dies nicht - Sie öffnen Ihre App für Sicherheitsprobleme, wenn Sie Benutzereingaben über diesen Code weitergeben. Verwenden Sie rimrafstattdessen eine getestete Bibliothek wie .
Wir sind alle Monica

Rimraf akzeptiert Saiten zu Alter, es ist nicht sicherer als dies
Alexander Mills

Das spezifische Problem ist, dass es sehr einfach ist, aus dem von Ihnen eingerichteten Zitat auszubrechen und beliebige Shell-Befehle auszuführen. rimrafhat dieses Problem nicht, weil es die Shell nicht verwendet. Außerdem wird im Allgemeinen eine gut gepflegte Bibliothek aktualisiert, wenn weitere Probleme auftreten, und ein einmaliger Code wie dieser wird dies nicht tun.
Wir sind alle Monica

@jnylen das ist Backend-Code - es kann nicht einfach von einem schlechten Schauspieler geändert werden
Alexander Mills

Wenn dieser Code Benutzereingaben in der dirVariablen akzeptiert, kann Ihr Server kompromittiert werden. Wenn jemand anderes diesen Code an einen Ort kopiert, an dem Benutzereingaben in die dirVariable akzeptiert werden, kann der Server kompromittiert werden.
Wir sind alle Monica
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.