В моем приложении Node мне нужно удалить каталог с несколькими файлами, но fs.rmdir
работает только в пустых каталогах. Как я могу это сделать?Удалить каталог, который не пуст
ответ
Существует модуль для этого: rimraf
(https://npmjs.org/package/rimraf). Она обеспечивает такую же функциональность как rm -Rf
Основное использование:
var rimraf = require('rimraf');
rimraf('/some/directory', function() { console.log('done'); });
Я написал эту функцию, называемую папку удалить. Он будет рекурсивно удалять все файлы и папки в определенном месте. Единственный требуемый пакет - асинхронный.
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)
})
})
})
}
Идея состоит в том, чтобы не писать собственный код, если он уже написан кем-то другим. Лучший способ сделать это - использовать rimraf или fs-extra или любой другой модуль узла, чтобы выполнить эту работу для вас. –
Да, писать собственный код ужасно, потому что использование десятков сторонних модулей для относительно тривиальных операций никогда не оказывало каких-либо недостатков в крупномасштабных приложениях. – Eric
@ Эрик - подумал, что вам понравится напоминать о вашем комментарии после феномена «левого пэда» »! –
Чтобы удалить папку, синхронно
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);
}
};
Возможно, вы захотите добавить некоторые проверки, которые вы не собираетесь случайно запускать в '/'. Например, передача пустого пути и опечатка в файле может привести к тому, что curPath будет корневым. –
Более надежная реализация: замените «var curPath = path +»/«+ file;» с помощью var varPath = p.join (путь, файл); 'если вы включили модуль пути:' var p = require ("path") ' – Andry
Windows имеет \ slashes, поэтому' путь.join (dirpath, file) 'должен быть лучше, чем' path + "/" + file' – thybzi
Просто используйте rmdir module! это легко и просто.
Я достиг здесь, пытаясь перебраться с gulp
, и я пишу для дальнейших целей.
gulp-clean
осуждается дляgulp-rimraf
gulp-rimraf
осуждается в пользуdelete-files-folders
Если вы хотите удалить файлы и папки с помощью del
, вы должны добавить /**
для рекурсивного удаления.
gulp.task('clean', function() {
return del(['some/path/to/delete/**']);
});
Большинство людей, использующих fs
с Node.js хотел бы функции, близкие к «Unix путь» иметь дело с файлами. Я использую fs-extra принести все интересные вещи:
фс-экстра содержит методы, которые не включены в пакете фсов ванили Node.js. Такие, как mkdir -p, cp -r и rm -rf.
Еще лучше, фс-экстра капля замены для родных фс. Все методы в fs не модифицируются и привязаны к нему. Это означает, что вы можете заменить фс на фс-EXTRA:
// this can be replaced
var fs = require('fs')
// by this
var fs = require('fs-extra')
, а затем ... 'fs.removeSync ('/ tmp/myFolder');' или 'fs.remove ('/ tmp/myFolder', callback) ; ' –
с использованием Promise, удалить каталог Асинхронный ..
MyObject.prototype.removeDir = function (path) {
var executor = (resolve, reject)=> {
var relativePath = "";
//lets read the directory first
fs.readdir(path, (err, files)=> {
let fLen = files.length;
//if this directory doesn't contain any file lets just delete it and then resolve or reject..
//depending on whether there is an error or not
if (fLen === 0) {
fs.rmdir(path, (err)=> {
if (err) return reject(err); else return resolve(true)
});
}
//remember its asynchronous... so the loop runs without a block
for (let i = 0; i < fLen; i++) {
//append each fileName to the directory path to get is relativePath
relativePath = path + "/" + files[i];
//we also need to be sure the file is indeed a file or a directory
fs.stat(relativePath, (err, stats)=> {
if (err) {
console.log(err);
return err
}
if (stats.isFile()) {
fs.unlink(relativePath, (err)=> {
if (err) return reject(err);
console.log("fs.unlink");
//if we have gotten to the last file within the directory we can now delete it
if (i === fLen - 1) {
fs.rmdir(path, (err)=> {
if (err) return reject(err); else return resolve(true)
});
}
});
}
//so if there is a directory within this directory we should delete it as well
else if (stats.isDirectory()) {
//recursively deletes directory within a directory
this.removeDir(relativePath);
}
console.log("fs.Stat");
});
}
});
};
return new Promise(executor);
};
Зачем расширять объект? – programmer5000
Нет, извините, это не намерение. это скорее местозаполнитель того, что когда-либо было вашим объектом. я отредактирую его @ programmer5000 –
Зачем расширять * любой * объект? – programmer5000
Я хотел было способ сделать это без дополнительных модулей для чего-то столь крохотного и общего, но это лучшее, что я мог придумать.
Обновление: Должно быть теперь работать с 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);
});
}
Вот версия асинхронной из @SharpCoder's answer
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);
});
});
});
};
Мой модифицированном ответ от @oconnecp (https://stackoverflow.com/a/25069828/3027390)
Использует path.join для лучшего опыта кросс-платформенной. Итак, не забудьте потребовать его.
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);
}
}
Другой альтернативой является использование модуля fs-promise
, который обеспечивает promisified версии 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)
Примечание: асинхронная/Await требует недавно nodejs версии (7.6+)
версия Promisified:
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))
}
быстрый и грязный способ (возможно, для тестирования) может быть непосредственно использовать exec
или spawn
метод для вызова вызова ОС для удаления каталога. Подробнее о NodeJs child_process.
let exec = require('child_process').exec
exec('rm -Rf /tmp/*.zip', callback)
Downsides являются:
- Вы в зависимости от базовой ОС т.е. тот же метод будет работать в Unix/Linux, но, вероятно, не в окнах.
- Вы не можете захватить процесс на условиях или ошибках. Вы просто отдаете задачу базовой ОС и ждете возврата кода выхода.
Преимущества:
- Эти процессы могут выполняться асинхронно.
- Вы можете прослушивать вывод/ошибку команды, поэтому вывод команды не теряется. Если операция не завершена, вы можете проверить код ошибки и повторить попытку.
Если вы используете узел 8+ хотите asyncronicity и не хотите внешних зависимостей, вот асинхронная/Await версия:
const path = require('path');
const fs = require('fs');
const util = require('util');
const exists = util.promisify(fs.exists);
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) => {
if (await exists(dir)) {
const files = await readdir(dir);
await Promise.all(files.map(async (file) => {
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}`);
}
}))
await rmdir(dir);
console.log(`Removed dir ${dir}`);
}
}
- 1. Как удалить каталог, который не пуст?
- 2. Удалить каталог, который не пуст на python
- 3. Удалить каталог не пуст
- 4. Не удается удалить элемент. Каталог не пуст
- 5. каталог пуст или удален, не может удалить каталог
- 6. Как удалить текст каталога, если каталог пуст
- 7. Как удалить родительский каталог, если 2-й дочерний каталог пуст?
- 8. Проверьте, не пуст ли каталог
- 9. Android: SyncException: каталог не пуст?
- 10. Tensorflow ошибка установки - (каталог не пуст)
- 11. Каталог работ Tomcat пуст
- 12. PHP пуст каталог/папка
- 13. Как удалить узел данных, который не пуст в zookeeper?
- 14. Ошибка: ENOTEMPTY, каталог не пуст в Meteorjs
- 15. ASPNETCOMPILER: ошибка ASPRUNTIME: Целевой каталог не пуст
- 16. Баша: не показывать результаты, если каталог пуст
- 17. удалить каталог с подкаталогом (не пустым)
- 18. Не удается удалить каталог
- 19. gitlab - невозможно удалить/удалить каталог
- 20. Как проверить, пуст ли каталог?
- 21. Solr 5.1.0 каталог dataimporthandler пуст
- 22. Быстрый тест, если каталог пуст
- 23. Lua - Удалить непустой каталог
- 24. Почему не удается удалить каталог, который был chmoded 777?
- 25. Java nio - не удается удалить каталог, который был опустошен
- 26. Невозможно удалить каталог
- 27. Git удалить каталог
- 28. Почему каталог, на который ссылается ресурс pathpath null, если каталог пуст?
- 29. MSBuild не удается удалить каталог Бинарники
- 30. PHP не может удалить каталог
Существует также синхронная версия: rimraf.sync ('/ некоторые/каталог '); –