Usuń katalog, który nie jest pusty

298

W mojej aplikacji Node muszę usunąć katalog, który zawiera niektóre pliki, ale fs.rmdirdziała tylko w pustych katalogach. W jaki sposób mogę to zrobić?

sachin
źródło
1
W skrócie: fs.readdir(dirPath)dla tablicy ścieżek w folderze, iteruj, fs.unlink(filename)aby usunąć każdy plik, a następnie w końcu, fs.rmdir(dirPath)aby usunąć teraz pusty folder. Jeśli musisz się powtórzyć, sprawdź fs.lstat(filename).isDirectory().
iono

Odpowiedzi:

319

Jest do tego moduł o nazwie rimraf( https://npmjs.org/package/rimraf ). Zapewnia taką samą funkcjonalność jakrm -Rf

Wykorzystanie asynchroniczne :

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

Wykorzystanie synchronizacji :

rimraf.sync("/some/directory");
Morgan ARR Allen
źródło
1
Dziwne, nigdy nie widziałem takiego zachowania. Sugeruję poszukiwanie i / lub zgłoszenie błędu. github.com/isaacs/rimraf/issues
Morgan ARR Allen
35
Jest to coś, co można łatwo zrobić za pomocą bibliotek NodeJS Core, po co instalować nieobsługiwany pakiet innej firmy?
SudoKid
4
@EmettSpeer Kiedy rozumiesz pojęcie „łatwo zrobić”? Samo pisanie funkcji jak deleteFolderRecursivew poniższej odpowiedzi?
Freewind,
23
„ale nawet z funkcją poniżej jest lepsza niż dodanie niepotrzebnego pakietu do systemu.” Definitywnie się z tym nie zgadzam. Po raz kolejny wymyślasz koło po raz dziewiętnasty, zupełnie bez żadnego powodu, ryzykując wprowadzeniem błędów lub luk w zabezpieczeniach. Przynajmniej to strata czasu. Inb4 „co jeśli upuszczą pakiet”: w bardzo mało prawdopodobnym przypadku, gdy pakiet zostanie usunięty z rejestru npm, zawsze możesz go zastąpić własnym . Nie ma sensu bandażować głowy, zanim ją złamiesz.
Demonblack
3
możesz teraz użyć recursiveopcji: stackoverflow.com/a/57866165/6269864
243

Aby usunąć folder synchronicznie

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);
  }
};
SharpCoder
źródło
33
Może chcesz dodać kilka sprawdzeń, że nie zamierzasz przypadkowo uruchomić tego na '/'. Na przykład przekazanie pustej ścieżki i literówki w pliku może spowodować, że curPath będzie katalogiem głównym.
Jake_Howard
9
Bardziej wytrzymałe wykonanie: wymienić var curPath = path + "/" + file;z var curPath = p.join(path, file);warunkiem, że zawiera moduł ścieżki:var p = require("path")
Andry
9
Windows ma \ ukośniki, więc path.join(dirpath, file)powinno być lepiej niżpath + "/" + file
thybzi
5
Możesz otrzymać „Przekroczono maksymalny rozmiar stosu wywołań” z tym kodem z powodu zbyt wielu operacji w jednym czasie zaznaczenia. @W połowie, jeśli uruchamiasz aplikację konsolową, masz 1 klienta, nie więcej. W tym przypadku nie ma potrzeby używania asynchronizacji aplikacji konsolowej
Leonid Dashko
4
Otrzymuję komunikat „Błąd: ENOTEMPTY: katalog nie jest pusty”
Mewa
168

Większość osób korzystających fsz Node.js chciałoby funkcji zbliżonych do „uniksowego sposobu” radzenia sobie z plikami. Korzystam z fs-extra, aby przynieść wszystkie fajne rzeczy:

fs-extra zawiera metody, które nie są zawarte w waniliowym pakiecie fs Node.js. Takich jak mkdir -p, cp -r i rm -rf.

Jeszcze lepiej, fs-extra jest spadkiem w zastępstwie natywnego fs. Wszystkie metody w fs są niezmodyfikowane i dołączone do niego. Oznacza to, że możesz zastąpić fs przez fs-extra :

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

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

Następnie możesz usunąć folder w ten sposób:

fs.removeSync('/tmp/myFolder'); 
//or
fs.remove('/tmp/myFolder', callback);
Pierre Maoui
źródło
dla potrzebnej wersji synchronizacjiremoveSync('/tmp/myFolder')
olidem
148

Od 2019 roku ...

Począwszy od Node.js 12.10.0 , fs.rmdirSyncobsługuje recursiveopcje, dzięki czemu możesz w końcu wykonać:

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

Gdzie recursiveopcja rekurencyjnie usuwa cały katalog.

K - Toksyczność w SO rośnie.
źródło
5
@anneb Dzieje się tak, jeśli używasz starszej wersji Node.js (<12.10). Najnowsza wersja rozpoznaje tę opcję recursive: truei usuwa niepuste foldery bez reklamacji.
GOTO 0
9
Usuwanie rekurencyjne jest nadal eksperymentalne od węzła v13.0.1
Tim
5
Podpis funkcji jest faktycznie fs.rmdir(path[, options], callback)lubfs.rmdirSync(path[, options])
conceptdeluxe
@Tim, co masz na myśli przez eksperymentalne?
Emerica
2
@Emerica W oficjalnych dokumentach node.js znajduje się duże, pomarańczowe powiadomienie z informacją, że fs.rmdirjest eksperymentalna ze stabilnością 1. „Stabilność: 1 - eksperymentalna. Funkcja nie podlega regułom wersjonowania semantycznego. W dowolnym przyszłe wydanie. Korzystanie z tej funkcji nie jest zalecane w środowiskach produkcyjnych ”.
Tim
24

Moja zmodyfikowana odpowiedź od @oconnecp ( https://stackoverflow.com/a/25069828/3027390 )

Używa path.join dla lepszego doświadczenia na różnych platformach. Więc nie zapomnij tego wymagać.

var path = require('path');

Również przemianowano funkcję na 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);
    }
}
thybzi
źródło
17

Zwykle nie wskrzeszam starych wątków, ale tutaj jest dużo churn i bez odpowiedzi rimrafa wszystkie te wydają mi się zbyt skomplikowane.

Po pierwsze we współczesnym węźle (> = v8.0.0) możesz uprościć ten proces, używając tylko modułów rdzenia węzła, w pełni asynchronicznych, i równolegle rozłączać pliki jednocześnie w funkcji pięciu linii i nadal zachować czytelność:

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);
};

Z drugiej strony strażnik przed atakami z przejścia ścieżki jest nieodpowiedni dla tej funkcji, ponieważ

  1. Jest to poza zakresem oparte na zasadzie jednolitej odpowiedzialności .
  2. Powinien być obsługiwany przez dzwoniącego, a nie tę funkcję. Jest to podobne do wiersza poleceń rm -rf, ponieważ wymaga argumentu i pozwala użytkownikowi na to, rm -rf /jeśli zostanie o to poproszony. Skrypt byłby odpowiedzialny za ochronę rmsamego programu.
  3. Ta funkcja nie byłaby w stanie określić takiego ataku, ponieważ nie ma ram odniesienia. Ponownie jest to obowiązkiem dzwoniącego, który miałby kontekst intencji, który zapewniłby mu odniesienie do porównania przejścia ścieżki.
  4. Sym-linki nie są problemem, jak .isDirectory()to falsena sym-linków i nie są odłączone recursed się.

Wreszcie, istnieje rzadki warunek wyścigu, w którym rekursja może popełnić błąd, jeśli jeden z wpisów został rozłączony lub usunięty poza tym skryptem we właściwym czasie, gdy ta rekurencja jest uruchomiona. Ponieważ ten scenariusz nie jest typowy w większości środowisk, prawdopodobnie można go przeoczyć. Jednak w razie potrzeby (w niektórych przypadkach skrajnych) ten problem można złagodzić za pomocą nieco bardziej złożonego przykładu:

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);
};

EDYCJA: Utwórz isDirectory()funkcję. Usuń rzeczywisty katalog na końcu. Napraw brakującą rekurencję.

Sukima
źródło
1
To naprawdę fajne rozwiązanie. Pytanie dotyczące drugiej próbki kodu: nie zadzwonić awaitna własną Promise.all(…); czy to celowe? Wygląda na to, że w obecnym stanie results.forEachiterowałby nad obietnicami, podczas gdy kod oczekuje iteracji nad wynikami. Czy coś brakuje?
Anton Strogonoff
@ Tony masz rację, to jest literówka / błąd. Dobry chwyt!
Sukima
Może najpierw sprawdzisz, czy katalog istnieje? coś w styluif (!fs.existsSync(dir)) return
GTPV
@GTPV Dlaczego? Zwiększa to odpowiedzialność tej funkcji. readdirwyrzuci błąd tak, jak powinien. Jeśli rmdir non-existing-dirkod wyjścia jest błędem. Próbowanie / łapanie byłoby obowiązkiem konsumenta. Jest to ta sama metoda, którą opisano w dokumentach węzła, jeśli chodzi o korzystanie z funkcji fs. Oczekują, że spróbujesz / złapiesz i spojrzysz na błędy, codeaby ustalić, co zrobić. Dodatkowa kontrola wprowadza warunek wyścigu.
Sukima,
Zdecydowanie rozumiem twój punkt widzenia. Spodziewałbym się jednak intuicyjnie, że próba usunięcia nieistniejącego folderu byłaby udana, ponieważ po prostu nic nie zrobiłaby. Brak warunków wyścigu, jeśli fs.existsużywana jest wersja synchroniczna . PS to świetne rozwiązanie.
GTPV
12

Oto asynchroniczna wersja odpowiedzi @ 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);
            });
        });
    });
};
Tony Brix
źródło
10

Napisałem tę funkcję o nazwie remove folder. Rekurencyjnie usunie wszystkie pliki i foldery w lokalizacji. Jedyny wymagany pakiet to asynchronizacja.

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)
            })
        })
    })
}
oconnecp
źródło
4
Chodzi o to, aby nie pisać własnego kodu, jeśli został już napisany przez kogoś innego. Lepszym sposobem na to jest skorzystanie z rimraf lub fs-extra lub dowolnego innego modułu węzła, aby wykonać pracę za Ciebie.
Victor Pudeyev
90
Tak, pisanie własnego kodu jest okropne, ponieważ używanie dziesiątek modułów innych firm do stosunkowo trywialnych operacji nigdy nie wykazało żadnych wad w aplikacjach na dużą skalę.
Eric
8

Jeśli używasz węzła 8+, chcesz asynchroniczności i nie chcesz zewnętrznych zależności, oto wersja asynchroniczna / oczekująca:

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);
    }
}
RonZ
źródło
4

Wersja asynchroniczna odpowiedzi @ SharpCoder przy użyciu 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);
    }
};
Błąd 404
źródło
3

Dotarłem tutaj, próbując się z tym gulppogodzić i piszę o dalszych zasięgach.

Jeśli chcesz usunąć pliki i foldery za pomocą del, powinieneś dołączyć /**do usunięcia rekurencyjnego.

gulp.task('clean', function () {
    return del(['some/path/to/delete/**']);
});
Jin Kwon
źródło
2

Pakiet de facto jest rimraf, ale oto moja mała wersja asynchroniczna:

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))
}
clarkttfu
źródło
2

Zgodnie z fsdokumentacją , fsPromisesobecnie daje recursiveopcję na zasadzie eksperymentu, który, przynajmniej w moim przypadku na Windows, usuwa katalog i wszystkie pliki w nim.

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

Czy recursive: trueusuwa pliki w systemie Linux i MacOS?

stary chłopiec
źródło
1

Ultraszybka i odporna na awarie

Możesz użyć lignatorpakietu ( https://www.npmjs.com/package/lignator ), jest szybszy niż jakikolwiek kod asynchroniczny (np. Rimraf) i bardziej odporny na awarie (szczególnie w systemie Windows, w którym usuwanie plików nie jest natychmiastowe, a pliki mogą być zablokowane przez inne procesy).

4,36 GB danych, 28 042 plików, 4 217 folderów w systemie Windows usuniętych w 15 sekund w porównaniu do 60 sekund rimrafa na starym dysku twardym.

const lignator = require('lignator');

lignator.remove('./build/');
HankMoody
źródło
1

Synchronizuj folder usuń z plikami lub tylko z plikiem.

Nie jestem dawcą ani współpracownikiem, ale nie mogłem znaleźć dobrego rozwiązania tego problemu i musiałem znaleźć swoją drogę ... więc mam nadzieję, że ci się spodoba :)

Działa idealnie dla mnie z dowolną liczbą zagnieżdżone katalogi i podkatalogi. Uwaga na zakres „tego” przy rekursywnej funkcji, twoja implementacja może być inna. W moim przypadku funkcja ta pozostaje w zwrocie innej funkcji, dlatego właśnie ją w ten sposób nazywam.

    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);
        }
MetaTron
źródło
1

Chociaż recursivejest eksperymentalną opcjąfs.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);
            });
        });
    });
}
Aikon Mogwai
źródło
1

Aktualizacja 2020

Od wersji 12.10.0 dodano opcję recursiveOption dla opcji.

Pamiętaj, że usuwanie rekurencyjne jest eksperymentalne .

Zrobiłbyś więc synchronizację:

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

lub asynchronicznie:

fs.rmdir(dir, {recursive: true});
Giovanni Patruno
źródło
0

Wystarczy użyć modułu rmdir ! to łatwe i proste.

Aminowski
źródło
6
Nie zawsze dobrym pomysłem jest użycie modułu dla każdego małego fragmentu kodu. Jeśli na przykład musisz utworzyć umowę licencyjną, powoduje to prawdziwy ból.
Mijago,
4
musisz dodać przykładowy kod, aby twoja odpowiedź była bardziej interesująca
Xeltor
0

Inną alternatywą jest użycie fs-promisemodułu, który zapewnia obiecane wersje fs-extramodułów

możesz wtedy napisać jak w tym przykładzie:

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)

Uwaga: async / await wymaga najnowszej wersji nodejs (7.6+)

Max Fichtelmann
źródło
0

Szybkim i brudnym sposobem (być może do testowania) może być bezpośrednie użycie metody execlub w spawncelu wywołania wywołania systemu operacyjnego w celu usunięcia katalogu. Przeczytaj więcej na temat procesu potomnego NodeJs .

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

Minusy to:

  1. Jesteś zależny od systemu operacyjnego, tzn. Ta sama metoda działałaby w systemie Unix / Linux, ale prawdopodobnie nie w systemie Windows.
  2. Nie możesz przejąć procesu z powodu błędów lub warunków. Po prostu powierz zadanie bazowemu systemowi operacyjnemu i poczekaj, aż kod wyjścia zostanie zwrócony.

Korzyści:

  1. Te procesy mogą działać asynchronicznie.
  2. Możesz nasłuchiwać danych wyjściowych / błędów polecenia, dlatego dane wyjściowe polecenia nie zostaną utracone. Jeśli operacja nie zostanie zakończona, możesz sprawdzić kod błędu i spróbować ponownie.
Wysypka
źródło
2
Idealne, gdy piszesz skrypt i nie chcesz instalować zależności, ponieważ masz zamiar usunąć ten skrypt w 30 sekund po usunięciu wszystkich plików !!
Mathias
Zawsze są sposoby na zepsucie i usunięcie głównego systemu plików. W takim przypadku OP może usunąć -fflagę, aby być bezpiecznym lub upewnić się podczas pisania, że ​​nie usunie wszystkiego. exec + rmto poprawne i przydatne polecenie w węźle, którego często używam podczas testowania.
Wysypka
0

Chciałbym, aby istniał sposób na to bez dodatkowych modułów dla czegoś tak małego i powszechnego, ale to jest najlepsze, co mogłem wymyślić.

Aktualizacja: powinien teraz działać w systemie Windows (testowany system Windows 10), a także powinien działać na systemach Linux / Unix / BSD / Mac.

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);
    });
}
b01
źródło
Może fs-extra jest dobrym rozwiązaniem, jeśli chcesz mieć pojedynczy moduł.
b01
3
Ta metoda jest wręcz niebezpieczna. Łączenie łańcuchowe polecenia powłoki, szczególnie bez ucieczki, zachęca do luk w wykonywaniu kodu i tym podobnych. Jeśli zamierzasz użyć rmdir, użyj, child_process.execFilektóry nie wywołuje powłoki, i zamiast tego przekazuj jawnie argumenty.
Nevyn
@nevyn Spróbuję zaktualizować odpowiedź, jeśli zadziała.
b01
Zawsze wolą nie korzystać z usług stron trzecich! Dzięki!
Anton Mitsev,
Ponadto ta metoda jest dość powolna. Natywny interfejs API Nodejsa jest znacznie szybszy.
mersey,
0

Jest to jedno podejście wykorzystujące promisify i dwie funkcje pomocy (do i do wszystkich), aby rozwiązać obietnicę.

Wszystkie działania są asynchroniczne.

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)
    }
}; 
Aecio Levy
źródło
0

// bez użycia jakiejkolwiek biblioteki osób trzecich

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);
Amy
źródło
1
To zadziała na to, czego potrzebuję, ale możesz chcieć użyć ścieżki zamiast łączenia slash:fs.unllinkSync(path.join(FOLDER_PATH, element);
jackofallcode
-1
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!')
  }
}
Erisan Olasheni
źródło
1
Myślę, że coś takiego powinno działać w zagnieżdżonych katalogach.
fool4jesus
Tak, zarówno dla katalogu zagnieżdżonego, jak i katalogu nie zagnieżdżonego
Erisan Olasheni