Удалить каталог, который не пуст
в моем узле приложения мне нужно удалить каталог, который имеет некоторые файлы, но fs.rmdir
работает только с пустыми каталогами. Как я могу это сделать?
16 ответов:
есть модуль для этого называется
rimraf
(https://npmjs.org/package/rimraf). он обеспечивает ту же функциональность, что иrm -Rf
основное использование:
var rimraf = require('rimraf'); rimraf('/some/directory', function () { console.log('done'); });
удалить папку синхронно
var fs = require('fs'); var deleteFolderRecursive = function(path) { if (fs.existsSync(path)) { fs.readdirSync(path).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); } };
большинство людей, используя
fs
С узла.js хотел бы, чтобы функции были близки к "Unix-способу" работы с файлами. Я использую fs-extra чтобы принести все классные вещи:fs-extra содержит методы, которые не включены в узел vanilla.js пакет ФС. Например, команды mkdir -Р, ПУ -р и РМ -РФ.
еще лучше, fs-extra это капля в замене для родной fs. Все методы в fs не модифицированы и прикреплены к оно. Это означает, что вы можете заменить ДФ на fs-extra:
// this can be replaced var fs = require('fs') // by this var fs = require('fs-extra')
и затем вы можете удалить папки таким образом:
fs.removeSync('/tmp/myFolder'); //or fs.remove('/tmp/myFolder', callback);
мой измененный ответ от @oconnecp (https://stackoverflow.com/a/25069828/3027390)
использует пути.присоединяйтесь для лучшего кросс-платформенного опыта. Так что, не забудьте потребовать его.
var path = require('path');
переименовал функцию
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); } }
вот асинхронная версия @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); }); }); }); };
Я написал эту функцию удалить папку. Это будет рекурсивно удалить все файлы и папки на месте. Единственный пакет, который он требует, - это асинхронность.
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) }) }) }) }
Если вы используете узел 8 + хотите асинхронность и не хотите внешних зависимостей, вот версия async / await:
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); } }
я добрался сюда, пытаясь покончить с
gulp
и я пишу для дальнейшего достигает.
gulp-clean
удаленgulp-rimraf
gulp-rimraf
deprecated в пользуdelete-files-folders
если вы хотите удалить файлы и папки с помощью
del
, вы должны добавить/**
для рекурсивного удаления.gulp.task('clean', function () { return del(['some/path/to/delete/**']); });
просто использовать модуль rmdir! это легко и просто.
обещанная версия:
const fs = require('fs') const path = require('path') const Q = require('q') function rmdir(dir) { return Q.nfcall(fs.access, dir).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())) }, err => {}) .then(() => Q.nfcall(fs.rmdir, dir)) }
Другой альтернативой является использование
fs-promise
модуль, который обеспечивает обещанные версииfs-extra
модуливы могли бы написать такой пример:
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)
Примечание: async / await требует последней версии nodejs (7.6+)
Я хотел было способ, чтобы сделать это без дополнительных модулей за какой-то мизер, но это лучшее, что я мог придумать.
обновление: Теперь должен работать на Windows (проверено Windows 10), а также должен работать на системах 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 sinle 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); }); }
быстрый и грязный способ (возможно, для проверки) может быть непосредственно использовать
exec
илиspawn
метод вызова вызова ОС для удаления каталога. Подробнее читайте на child_process NodeJs.let exec = require('child_process').exec exec('rm -Rf /tmp/*.zip', callback)
недостатки:
- вы зависите от базовой ОС, т. е. тот же метод будет работать в unix/linux, но, вероятно, не в windows.
- вы не можете захватить процесс на условия или ошибки. Вы просто передайте задачу базовой ОС и дождитесь возврата кода выхода.
преимущества:
- эти процессы могут выполняться асинхронно.
- вы можете прослушать вывод / ошибку команды, поэтому вывод команды не теряется. Если операция не завершена, можно проверить код ошибки и повторить попытку.
асинхронная версия ответа @SharpCoder с использованием 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); } };
const fs = require('fs') const path = require('path') let _dirloc = '<path_do_the_directory>' if(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!') } }