Antworten:
Hierfür gibt es ein Modul namens rimraf
( https://npmjs.org/package/rimraf ). Es bietet die gleiche Funktionalität wierm -Rf
Asynchrone Verwendung:
var rimraf = require("rimraf");
rimraf("/some/directory", function () { console.log("done"); });
Synchronisierungsnutzung :
rimraf.sync("/some/directory");
deleteFolderRecursive
in der folgenden Antwort schreiben ?
recursive
Option verwenden: stackoverflow.com/a/57866165/6269864
Ordner synchron entfernen
const fs = require('fs');
const Path = require('path');
const deleteFolderRecursive = function(path) {
if (fs.existsSync(path)) {
fs.readdirSync(path).forEach((file, index) => {
const curPath = Path.join(path, file);
if (fs.lstatSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
};
var curPath = path + "/" + file;
mit var curPath = p.join(path, file);
bereitgestellten enthalten Sie den Pfad - Modul:var p = require("path")
path.join(dirpath, file)
sollte also besser sein alspath + "/" + file
Die meisten fs
Benutzer von Node.js möchten Funktionen, die der "Unix-Methode" für den Umgang mit Dateien nahe kommen. Ich benutze fs-extra , um all die coolen Sachen zu bringen:
fs-extra enthält Methoden, die nicht im Paket vanilla Node.js fs enthalten sind. Wie mkdir -p, cp -r und rm -rf.
Noch besser ist, dass fs-extra ein Ersatz für native fs ist. Alle Methoden in fs sind unverändert und damit verbunden. Dies bedeutet, dass Sie fs durch fs-extra ersetzen können :
// this can be replaced
const fs = require('fs')
// by this
const fs = require('fs-extra')
Und dann können Sie einen Ordner folgendermaßen entfernen:
fs.removeSync('/tmp/myFolder');
//or
fs.remove('/tmp/myFolder', callback);
removeSync('/tmp/myFolder')
Ab Node.js 12.10.0 , fs.rmdirSync
unterstützt eine recursive
Auswahl, so dass Sie schließlich tun können:
fs.rmdirSync(dir, { recursive: true });
Wobei die recursive
Option das gesamte Verzeichnis rekursiv löscht.
recursive: true
und löscht nicht leere Ordner ohne Beanstandung.
fs.rmdir(path[, options], callback)
oderfs.rmdirSync(path[, options])
fs.rmdir
experimentell mit Stabilität 1 gearbeitet wird. "Stabilität: 1 - experimentell. Die Funktion unterliegt nicht den Regeln für die semantische Versionierung. In keinem Fall können nicht abwärtskompatible Änderungen oder Entfernungen auftreten zukünftige Version. Die Verwendung der Funktion wird in Produktionsumgebungen nicht empfohlen. "
Meine geänderte Antwort von @oconnecp ( https://stackoverflow.com/a/25069828/3027390 )
Verwendet path.join für eine bessere plattformübergreifende Erfahrung. Vergessen Sie also nicht, es zu verlangen.
var path = require('path');
Auch umbenannte Funktion in 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);
}
}
Normalerweise belebe ich alte Fäden nicht wieder, aber hier gibt es eine Menge Abwanderung und ohne Rimraf-Antwort. Diese scheinen mir alle zu kompliziert.
Erstens können Sie im modernen Knoten (> = v8.0.0) den Prozess vereinfachen, indem Sie nur vollständig asynchrone Knotenkernmodule verwenden und gleichzeitig die Verknüpfung von Dateien in einer Funktion von fünf Zeilen parallelisieren und trotzdem die Lesbarkeit beibehalten:
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);
};
In einem anderen Punkt ist ein Schutz für Pfadüberquerungsangriffe für diese Funktion ungeeignet, weil
rm -rf
, als es ein Argument akzeptiert und es dem Benutzer ermöglicht, rm -rf /
wenn er dazu aufgefordert wird. Es liegt in der Verantwortung eines Skripts, nicht das rm
Programm selbst zu schützen ..isDirectory()
ist false
für sym-Links und UNLINKED nicht rekursiv.Last but not least gibt es eine seltene Race-Bedingung, dass die Rekursion fehlerhaft sein kann, wenn einer der Einträge nicht verknüpft oder gelöscht wurde außerhalb dieses Skripts zum richtigen Zeitpunkt während der Ausführung dieser Rekursion nicht . Da dieses Szenario in den meisten Umgebungen nicht typisch ist, kann es wahrscheinlich übersehen werden. Bei Bedarf (für einige Randfälle) kann dieses Problem jedoch durch dieses etwas komplexere Beispiel behoben werden:
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);
};
BEARBEITEN: Machen Sie isDirectory()
eine Funktion. Entfernen Sie das eigentliche Verzeichnis am Ende. Fehlende Rekursion behoben.
await
Ihren nicht an Promise.all(…)
; ist das beabsichtigt? Es scheint, als results.forEach
würde der aktuelle Status Versprechungen durchlaufen, während der Code erwartet, dass er die Ergebnisse durchläuft. Vermisse ich etwas
if (!fs.existsSync(dir)) return
readdir
wird einen Fehler auslösen, wie es sollte. Wenn Sie rmdir non-existing-dir
den Exit-Code ist ein Fehler. Es liegt in der Verantwortung des Verbrauchers, es zu versuchen / zu fangen. Dies ist die gleiche Methode, die in den Node-Dokumenten beschrieben wird, wenn es um die Verwendung von fs-Funktionen geht. Sie erwarten, dass Sie versuchen / fangen und sich die Fehler ansehen, code
um festzustellen, was zu tun ist. Ein zusätzlicher Check führt eine Rennbedingung ein.
fs.exists
verwendet wird. PS das ist eine großartige Lösung.
Hier ist eine asynchrone Version der Antwort von @ SharpCoder
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);
});
});
});
};
Ich habe diese Funktion namens Ordner entfernen geschrieben. Es werden rekursiv alle Dateien und Ordner an einem Speicherort entfernt. Das einzige Paket, das benötigt wird, ist asynchron.
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)
})
})
})
}
Wenn Sie Knoten 8+ verwenden, möchten Sie Asynchronität und keine externen Abhängigkeiten. Hier ist die asynchrone / wartende 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);
}
}
Asynchrone Version der Antwort von @ SharpCoder mit 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);
}
};
Ich erreichte hier, während ich versuchte, mit dem fertig zu werden, gulp
und schreibe für weitere Reichweiten.
gulp-clean
veraltet für gulp-rimraf
gulp-rimraf
veraltet zugunsten von delete-files-folders
Wenn Sie Dateien und Ordner mit löschen möchten del
, sollten Sie sie /**
zum rekursiven Löschen anhängen .
gulp.task('clean', function () {
return del(['some/path/to/delete/**']);
});
Das De-facto-Paket ist rimraf
, aber hier ist meine winzige asynchrone 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))
}
In der neuesten Version von Node.js (12.10.0 oder höher), die rmdir
Stil - Funktionen fs.rmdir()
, fs.rmdirSync()
und fs.promises.rmdir()
haben eine neue experimentelle Option , recursive
die nicht-leere Verzeichnisse ermöglicht das Löschen, zB
fs.rmdir(path, { recursive: true });
Die zugehörige PR auf GitHub: https://github.com/nodejs/node/pull/29168
Laut fs
Dokumentation bietet fsPromises
derzeit die recursive
Option auf experimenteller Basis, die, zumindest in meinem Fall unter Windows, das Verzeichnis und alle darin enthaltenen Dateien entfernt.
fsPromises.rmdir(path, {
recursive: true
})
Entfernt recursive: true
die Dateien unter Linux und MacOS?
Ultra-Geschwindigkeit und ausfallsicher
Sie können das lignator
Paket verwenden ( https://www.npmjs.com/package/lignator ), es ist schneller als jeder asynchrone Code (z. B. rimraf) und ausfallsicherer (insbesondere in Windows, wo das Entfernen von Dateien nicht sofort erfolgt und Dateien möglicherweise nicht vorhanden sind durch andere Prozesse gesperrt sein).
4,36 GB Daten, 28 042 Dateien, 4 217 Ordner unter Windows wurden in 15 Sekunden entfernt, während Rimrafs 60 Sekunden auf einer alten Festplatte lagen .
const lignator = require('lignator');
lignator.remove('./build/');
Ordner mit den Dateien oder nur einer Datei entfernen.
Ich bin weder ein Geber noch ein Mitwirkender, aber ich konnte keine gute Lösung für dieses Problem finden und musste mich zurechtfinden ... also hoffe ich, dass es Ihnen gefällt :)
Funktioniert perfekt für mich mit einer beliebigen Anzahl von verschachtelte Verzeichnisse und Unterverzeichnisse. Achtung für den Umfang von 'this' bei der Rekursion der Funktion kann Ihre Implementierung anders sein. In meinem Fall bleibt diese Funktion in der Rückgabe einer anderen Funktion, deshalb rufe ich sie damit auf.
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);
}
Während recursive
ist eine experimentelle Option vonfs.rmdir
function rm (path, cb) {
fs.stat(path, function (err, stats) {
if (err)
return cb(err);
if (stats.isFile())
return fs.unlink(path, cb);
fs.rmdir(path, function (err) {
if (!err || err && err.code != 'ENOTEMPTY')
return cb(err);
fs.readdir(path, function (err, files) {
if (err)
return cb(err);
let next = i => i == files.length ?
rm(path, cb) :
rm(path + '/' + files[i], err => err ? cb(err) : next(i + 1));
next(0);
});
});
});
}
2020 Update
Ab Version 12.10.0 recursiveOption für Optionen hinzugefügt.
Beachten Sie, dass das rekursive Löschen experimentell ist .
Sie würden also für die Synchronisierung Folgendes tun:
fs.rmdirSync(dir, {recursive: true});
oder für Async:
fs.rmdir(dir, {recursive: true});
Verwenden Sie einfach das rmdir-Modul ! es ist leicht und einfach.
Eine andere Alternative ist die Verwendung des fs-promise
Moduls, das vielversprechende Versionen des bereitstelltfs-extra
Module
Sie könnten dann wie folgt schreiben:
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)
Hinweis: Für async / await ist eine aktuelle Version von nodejs (7.6+) erforderlich.
Ein schneller und schmutziger Weg (möglicherweise zum Testen) könnte darin bestehen, die Methode exec
oder direkt spawn
zum Aufrufen des Betriebssystemaufrufs zum Entfernen des Verzeichnisses zu verwenden. Lesen Sie mehr über NodeJs child_process .
let exec = require('child_process').exec
exec('rm -Rf /tmp/*.zip', callback)
Nachteile sind:
Leistungen:
-f
Flag entfernen , um die Sicherheit zu gewährleisten, oder während der Eingabe sicherstellen, dass nicht alles gelöscht wird. exec + rm
ist ein gültiger und nützlicher Befehl im Knoten, den ich beim Testen häufig verwende.
Ich wünschte, es gäbe eine Möglichkeit, dies ohne zusätzliche Module für etwas so Winziges und Gemeinsames zu tun, aber dies ist das Beste, was ich mir einfallen lassen könnte.
Update: Sollte jetzt unter Windows (getestet Windows 10) und auch unter Linux / Unix / BSD / Mac-Systemen funktionieren.
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);
});
}
child_process.execFile
das die Shell nicht aufruft, und übergeben Sie stattdessen explizit Argumente.
Dies ist ein Ansatz, bei dem promisify und zwei Hilfefunktionen (to und toAll) verwendet werden, um das Versprechen zu lösen.
Es führt alle Aktionen asynchron aus.
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)
}
};
// ohne Verwendung einer Drittanbieter-Bibliothek
const fs = require('fs');
var FOLDER_PATH = "./dirname";
var files = fs.readdirSync(FOLDER_PATH);
files.forEach(element => {
fs.unlinkSync(FOLDER_PATH + "/" + element);
});
fs.rmdirSync(FOLDER_PATH);
fs.unllinkSync(path.join(FOLDER_PATH, element);
const fs = require("fs")
const path = require("path")
let _dirloc = '<path_do_the_directory>'
if (fs.existsSync(_dirloc)) {
fs.readdir(path, (err, files) => {
if (!err) {
for (let file of files) {
// Delete each file
fs.unlinkSync(path.join(_dirloc, file))
}
}
})
// After the 'done' of each file delete,
// Delete the directory itself.
if (fs.unlinkSync(_dirloc)) {
console.log('Directory has been deleted!')
}
}
fs.readdir(dirPath)
Durchlaufen Sie für ein Array von Pfaden in einem Ordner diefs.unlink(filename)
einzelnen Dateien und anschließendfs.rmdir(dirPath)
den jetzt leeren Ordner. Wenn Sie rekursiv arbeiten müssen, überprüfen Siefs.lstat(filename).isDirectory()
.