Jawaban:
Ada modul untuk ini yang disebut rimraf
( https://npmjs.org/package/rimraf ). Ini menyediakan fungsi yang sama denganrm -Rf
Penggunaan Async :
var rimraf = require("rimraf");
rimraf("/some/directory", function () { console.log("done"); });
Sinkronkan penggunaan:
rimraf.sync("/some/directory");
deleteFolderRecursive
dalam jawaban berikut?
recursive
opsi: stackoverflow.com/a/57866165/6269864
Untuk menghapus folder secara sinkron
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;
dengan var curPath = p.join(path, file);
asalkan Anda menyertakan modul path:var p = require("path")
path.join(dirpath, file)
seharusnya lebih baik daripadapath + "/" + file
Sebagian besar orang yang menggunakan fs
Node.js ingin fungsi yang dekat dengan "cara Unix" berurusan dengan file. Saya menggunakan fs-extra untuk membawa semua barang keren:
fs-extra berisi metode yang tidak termasuk dalam paket fs vanilla Node.js. Seperti mkdir -p, cp -r, dan rm -rf.
Bahkan lebih baik, fs-extra adalah setetes pengganti fs asli. Semua metode dalam fs tidak dimodifikasi dan dilampirkan padanya. Ini berarti Anda dapat mengganti fs dengan fs-extra :
// this can be replaced
const fs = require('fs')
// by this
const fs = require('fs-extra')
Dan kemudian Anda dapat menghapus folder dengan cara ini:
fs.removeSync('/tmp/myFolder');
//or
fs.remove('/tmp/myFolder', callback);
removeSync('/tmp/myFolder')
Pada Node.js 12.10.0 , fs.rmdirSync
mendukung recursive
opsi, sehingga Anda akhirnya dapat melakukan:
fs.rmdirSync(dir, { recursive: true });
Di mana recursive
opsi menghapus seluruh direktori secara rekursif.
recursive: true
dan menghapus folder yang tidak kosong tanpa keluhan.
fs.rmdir(path[, options], callback)
ataufs.rmdirSync(path[, options])
fs.rmdir
eksperimental dengan stabilitas 1. "Stabilitas: 1 - Eksperimental. Fitur ini tidak tunduk pada aturan Semantic Versioning. Perubahan atau penghapusan yang tidak kompatibel mundur dapat terjadi pada setiap rilis mendatang. Penggunaan fitur ini tidak disarankan di lingkungan produksi. "
Jawaban saya yang dimodifikasi dari @oconnecp ( https://stackoverflow.com/a/25069828/3027390 )
Gunakan path.join untuk pengalaman lintas platform yang lebih baik. Jadi, jangan lupa untuk membutuhkannya.
var path = require('path');
Juga berganti fungsi menjadi 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);
}
}
Saya biasanya tidak menghidupkan kembali utas lama tetapi ada banyak churn di sini dan tanpa jawaban rimraf ini semua tampak terlalu rumit bagi saya.
Pertama di Node modern (> = v8.0.0) Anda dapat menyederhanakan proses hanya menggunakan modul inti simpul, sepenuhnya asinkron, dan memparalelkan penautan file secara bersamaan semua dalam fungsi lima baris dan masih dapat dibaca:
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);
};
Pada catatan lain penjaga untuk serangan jalur traversal tidak sesuai untuk fungsi ini karena
rm -rf
yang membutuhkan argumen dan akan memungkinkan pengguna untuk rm -rf /
jika diminta. Itu akan menjadi tanggung jawab naskah untuk menjaga bukan rm
program itu sendiri..isDirectory()
ini false
untuk sym-link dan dihapus linknya tidak recursed ke dalam.Terakhir namun tidak kalah pentingnya, ada kondisi balapan yang jarang terjadi bahwa rekursi dapat kesalahan jika salah satu entri dibatalkan tautannya atau dihapus di luar skrip ini pada waktu yang tepat saat rekursi ini berjalan. Karena skenario ini tidak khas di sebagian besar lingkungan, kemungkinan besar hal itu dapat diabaikan. Namun, jika diperlukan (untuk beberapa kasus tepi) masalah ini dapat dikurangi dengan contoh yang sedikit lebih kompleks ini:
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);
};
EDIT: Buat isDirectory()
fungsi. Hapus direktori yang sebenarnya di bagian akhir. Perbaiki rekursi yang hilang.
await
Anda Promise.all(…)
; Apakah ini disengaja? Sepertinya dalam kondisi saat ini results.forEach
akan beralih lebih dari janji, sementara kode mengharapkan untuk beralih pada hasil. Apakah saya melewatkan sesuatu?
if (!fs.existsSync(dir)) return
readdir
akan melempar kesalahan sebagaimana mestinya. Jika Anda rmdir non-existing-dir
kode keluar adalah kesalahan. Ini akan menjadi tanggung jawab konsumen untuk mencoba / menangkap. Ini adalah metode yang sama dijelaskan dalam Node docs ketika datang untuk menggunakan fungsi fs. Mereka mengharapkan Anda untuk mencoba / menangkap dan melihat kesalahan code
untuk menentukan apa yang harus dilakukan. Pemeriksaan tambahan menunjukkan kondisi balapan.
fs.exists
digunakan. PS ini adalah solusi bagus.
Ini adalah versi async dari jawaban @ 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);
});
});
});
};
Saya menulis fungsi ini disebut hapus folder. Itu akan secara rekursif menghapus semua file dan folder di suatu lokasi. Satu-satunya paket yang diperlukan adalah async.
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)
})
})
})
}
Jika Anda menggunakan node 8+ ingin asyncronicity dan tidak ingin dependensi eksternal, berikut adalah versi async / menunggu:
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);
}
}
Versi async dari jawaban @ SharpCoder menggunakan 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);
}
};
Saya sampai di sini sambil mencoba untuk melupakan gulp
dan saya menulis untuk mencapai lebih jauh.
gulp-clean
usang untuk gulp-rimraf
gulp-rimraf
usang dalam mendukung delete-files-folders
Saat Anda ingin menghapus file dan folder menggunakan del
, Anda harus menambahkan /**
untuk penghapusan rekursif.
gulp.task('clean', function () {
return del(['some/path/to/delete/**']);
});
Paket de facto adalah rimraf
, tetapi di sini adalah versi async kecil saya:
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))
}
Dalam versi terbaru dari Node.js (12.10.0 atau lambat), yang rmdir
fungsi gaya fs.rmdir()
, fs.rmdirSync()
dan fs.promises.rmdir()
memiliki pilihan eksperimental baru recursive
yang memungkinkan menghapus direktori yang tidak kosong, misalnya
fs.rmdir(path, { recursive: true });
PR terkait di GitHub: https://github.com/nodejs/node/pull/29168
Menurut fs
dokumentasi , fsPromises
saat ini menyediakan recursive
opsi berdasarkan percobaan, yang, setidaknya dalam kasus saya sendiri di Windows, menghapus direktori dan file apa pun di dalamnya.
fsPromises.rmdir(path, {
recursive: true
})
Apakah recursive: true
menghapus file di Linux dan MacOS?
Sangat cepat dan tahan gagal
Anda dapat menggunakan lignator
paket ( https://www.npmjs.com/package/lignator ), lebih cepat daripada kode async (misalnya rimraf) dan lebih banyak bukti kegagalan (terutama di Windows, di mana penghapusan file tidak instan dan file mungkin dikunci oleh proses lain).
4,36 GB data, 28.042 file, 4 217 folder pada Windows dihapus dalam 15 detik vs rimraf 60 detik pada HDD lama.
const lignator = require('lignator');
lignator.remove('./build/');
Folder Sync dihapus dengan file atau hanya file.
Saya bukan pemberi atau kontributor tetapi saya tidak dapat menemukan solusi yang baik untuk masalah ini dan saya harus menemukan jalan saya ... jadi saya harap Anda akan menyukainya :)
Bekerja sempurna untuk saya dengan sejumlah direktori dan sub direktori bersarang. Perhatian untuk ruang lingkup 'ini' ketika berulang fungsi, implementasi Anda mungkin berbeda. Dalam kasus saya fungsi ini tetap menjadi pengembalian fungsi lain itu sebabnya saya menyebutnya dengan ini.
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);
}
Sementara recursive
merupakan opsi eksperimental darifs.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);
});
});
});
}
Pembaruan 2020
Dari versi 12.10.0 rekursif Pilihan Pilihan telah ditambahkan untuk opsi.
Perhatikan bahwa penghapusan rekursif bersifat eksperimental .
Jadi yang akan Anda lakukan untuk sinkronisasi:
fs.rmdirSync(dir, {recursive: true});
atau untuk async:
fs.rmdir(dir, {recursive: true});
Cukup gunakan modul rmdir ! itu mudah dan sederhana.
Alternatif lain adalah menggunakan fs-promise
modul yang menyediakan versi promisified darifs-extra
modul
Anda kemudian dapat menulis seperti contoh ini:
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)
note: async / await membutuhkan versi nodejs terbaru (7.6+)
Cara cepat dan kotor (mungkin untuk pengujian) bisa langsung menggunakan exec
atau spawn
metode untuk memanggil panggilan OS untuk menghapus direktori. Baca lebih lanjut tentang proses child_pro NodeJs .
let exec = require('child_process').exec
exec('rm -Rf /tmp/*.zip', callback)
Kerugiannya adalah:
Manfaat:
-f
bendera agar aman, atau memastikan saat mengetik bahwa ia tidak akan menghapus semuanya. exec + rm
adalah perintah yang valid dan berguna dalam simpul yang sering saya gunakan selama pengujian.
Saya berharap ada cara untuk melakukan ini tanpa modul tambahan untuk sesuatu yang sangat kecil dan umum, tetapi ini adalah yang terbaik yang bisa saya lakukan.
Pembaruan: Sekarang seharusnya bekerja pada Windows (diuji Windows 10), dan juga harus bekerja pada sistem 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);
});
}
child_process.execFile
yang tidak memanggil shell, dan berikan argumen secara eksplisit.
Ini adalah satu pendekatan menggunakan fungsi promisify dan dua bantuan (ke dan untuk Semua) untuk menyelesaikan janji.
Itu semua tindakan asynchrounous.
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)
}
};
// tanpa menggunakan lib pihak ketiga
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)
untuk lintasan lintasan dalam folder, beralihlahfs.unlink(filename)
untuk menghapus setiap file, dan akhirnyafs.rmdir(dirPath)
menghapus folder yang sekarang kosong. Jika Anda perlu kambuh, periksafs.lstat(filename).isDirectory()
.