In meiner Node-Anwendung muss ich ein Verzeichnis entfernen, das einige Dateien enthält, aber fs.rmdir
funktioniert nur bei leeren Verzeichnissen. Wie kann ich das machen?
Antworten
Zu viele Anzeigen?Async-Version von @SharpCoders Antwort 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);
}
};
In einem asynchronen Ansatz, um ein nicht leeres Verzeichnis zu löschen,
rmdir(path, {recursive: true, force: true})
rm(path, {recursive: true, force: true})
wird funktionieren
Ein Code-Schnipsel:
const fsp = require("fs/promises");
deleteDirRecursively("./b");
removeRecursively("./BCD/b+");
async function deleteDirRecursively(dirPath) {
try {
// fsPromises.rmdir() für eine Datei (nicht ein Verzeichnis) führt dazu, dass das Versprechen abgelehnt wird
// mit einem ENOENT-Fehler unter Windows und einem ENOTDIR-Fehler unter POSIX.
// Um ein Verhalten ähnlich wie der Unix-Befehl rm -rf zu erhalten,
// verwenden Sie fsPromises.rm() mit den Optionen {recursive: true, force: true}.
// wird keinen Fehler werfen, wenn das Verzeichnis leer ist
// wirft Fehler, wenn das Verzeichnis nicht vorhanden ist
await fsp.rmdir(dirPath, { recursive: true, force: true });
console.log(dirPath, "erfolgreich gelöscht");
} catch (err) {
console.log(err);
}
async function removeRecursively(path) {
try {
// hat die Möglichkeit, sowohl Datei als auch Verzeichnis zu entfernen
// kann Verzeichnis rekursiv und zwangsweise löschen
// wird leeres Verzeichnis löschen.
// wird alle Inhalte eines Verzeichnisses entfernen.
// der einzige Unterschied zwischen rmdir und rm ist, dass rmdir nur Verzeichnisse löschen kann
await fsp.rm(path, { recursive: true, force: true });
console.log(path, "erfolgreich gelöscht");
} catch (err) {
console.log(err);
}
}
Ein schneller und einfacher Weg (vielleicht zum Testen) könnte sein, direkt die Methode exec
oder spawn
zu verwenden, um einen Betriebssystemaufruf zum Entfernen des Verzeichnisses auszuführen. Mehr dazu in der NodeJs child_process.
let exec = require('child_process').exec
exec('rm -Rf /tmp/*.zip', callback)
Nachteile sind:
- Du bist abhängig vom zugrunde liegenden Betriebssystem, d.h. die gleiche Methode würde in Unix/Linux laufen, aber wahrscheinlich nicht in Windows.
- Du kannst den Prozess bei Bedingungen oder Fehlern nicht übernehmen. Du überträgst einfach die Aufgabe an das zugrunde liegende Betriebssystem und wartest auf die Rückgabe des Exit-Codes.
Vorteile:
- Diese Prozesse können asynchron ausgeführt werden.
- Du kannst auf die Ausgabe/Fehler des Befehls hören, sodass die Befehlsausgabe nicht verloren geht. Wenn die Operation nicht abgeschlossen ist, kannst du den Fehlercode überprüfen und erneut versuchen.
Verwenden Sie einfach das rmdir-Modul! Es ist einfach und unkompliziert.
Das Standardpaket ist rimraf
, aber hier ist meine kleine 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))
}