回答:
このためのモジュールがありますrimraf
(https://npmjs.org/package/rimraf)。と同じ機能を提供しますrm -Rf
非同期の使用:
var rimraf = require("rimraf");
rimraf("/some/directory", function () { console.log("done"); });
同期の使用:
rimraf.sync("/some/directory");
deleteFolderRecursive
次の答えのような関数を自己記述しますか?
recursive
オプションを使用できるようになりました:stackoverflow.com/a/57866165/6269864
フォルダーを同期的に削除するには
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;
をvar curPath = p.join(path, file);
提供しますが、パスモジュールを含んでいた:var p = require("path")
path.join(dirpath, file)
より優れているはずですpath + "/" + file
fs
Node.jsを使用するほとんどの人は、ファイルを処理する「Unixの方法」に近い機能を望んでいます。私はすべてのクールなものをもたらすためにfs-extraを使用しています:
fs-extraには、通常のNode.js fsパッケージに含まれていないメソッドが含まれています。mkdir -p、cp -r、rm -rfなど。
さらに良いことに、fs-extraはネイティブfsに代わるものです。fsのすべてのメソッドは変更されておらず、それにアタッチされています。これは、fsをfs-extraで置き換えることができることを意味します。
// this can be replaced
const fs = require('fs')
// by this
const fs = require('fs-extra')
そして、あなたはこの方法でフォルダを削除することができます:
fs.removeSync('/tmp/myFolder');
//or
fs.remove('/tmp/myFolder', callback);
removeSync('/tmp/myFolder')
のとしてのNode.js 12.10.0、fs.rmdirSync
サポートされていrecursive
ますが、最終的に行うことができますので、オプション:
fs.rmdirSync(dir, { recursive: true });
このrecursive
オプションでは、ディレクトリ全体が再帰的に削除されます。
recursive: true
を認識し、空ではないフォルダーを問題なく削除します。
fs.rmdir(path[, options], callback)
またはfs.rmdirSync(path[, options])
fs.rmdir
安定性1で実験的であると言っている大きなオレンジ色の通知があります。将来のリリース。この機能を本番環境で使用することはお勧めしません。」
@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);
}
}
私は通常、古いスレッドを復活させることはしませんが、ここには多くのチャーンがあり、リムラフの回答を除き、これらはすべて私にとって複雑すぎるようです。
最初の最新のノード(> = v8.0.0)では、ノードコアモジュールのみを使用してプロセスを簡略化し、完全に非同期で、ファイルのリンク解除をすべて5行の関数で同時に並列化し、読みやすさを維持できます。
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);
};
別のメモでは、パストラバーサル攻撃のガードはこの機能には不適切です。
rm -rf
、引数を取り、rm -rf /
要求された場合にユーザーに許可するという点で、コマンドラインに似ています。保護しないのはスクリプトの責任ですrm
プログラム自体。.isDirectory()
ですfalse
SYM-リンク用とに再帰ないリンクが解除されています。最後に重要なことですが、この再帰の実行中に適切なタイミングでエントリの1つがこのスクリプトの外部でリンク解除または削除された場合、再帰がエラーになるというまれな競合状態があります。このシナリオはほとんどの環境では一般的ではないため、見落とされる可能性があります。ただし、必要に応じて(一部のエッジケースの場合)、この問題は、次の少し複雑な例で緩和できます。
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);
};
編集:isDirectory()
関数を作成します。最後に実際のディレクトリを削除します。欠落している再帰を修正します。
await
でくださいPromise.all(…)
。これは意図的ですか?現在の状態でresults.forEach
は、コードが結果を反復することを期待している間、promiseを反復するようです。何か不足していますか?
if (!fs.existsSync(dir)) return
readdir
必要に応じてエラーをスローします。あなたの場合はrmdir non-existing-dir
終了コードは誤りです。消費するのは消費者の責任です。これは、fs関数の使用に関して、ノードのドキュメントで説明されている方法と同じです。彼らはあなたがトライ/キャッチしてエラーを見てcode
何をすべきかを決定することを期待しています。追加のチェックにより、競合状態が発生します。
fs.exists
が使用されている場合、競合状態は発生しません。PSこれは素晴らしいソリューションです。
これは@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+を使用していて非同期性が必要で、外部依存関係が不要な場合は、非同期/待機バージョンを次に示します。
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);
}
}
fs.promisesを使用した@SharpCoder の応答の非同期バージョン:
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);
}
};
を乗り越えようとしているときにここに到達し、gulp
さらに到達するために書いています。
gulp-clean
非推奨 gulp-rimraf
gulp-rimraf
賛成して非推奨 delete-files-folders
を使用してファイルとフォルダを削除するdel
場合は/**
、再帰的に削除するために追加する必要があります。
gulp.task('clean', function () {
return del(['some/path/to/delete/**']);
});
デファクトパッケージはですがrimraf
、これが私の小さな非同期バージョンです。
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))
}
Node.jsの(12.10.0以降)の最新バージョンでは、rmdir
スタイル機能fs.rmdir()
、fs.rmdirSync()
およびfs.promises.rmdir()
新しい実験的なオプションを持っていますrecursive
非空のディレクトリを削除することができ、例えば
fs.rmdir(path, { recursive: true });
GitHubの関連PR:https : //github.com/nodejs/node/pull/29168
超高速でフェイルプルーフ
lignator
パッケージ(https://www.npmjs.com/package/lignator)を使用できます。これは、非同期コード(rimrafなど)よりも高速で、フェイルプルーフ(特にWindowsではファイルの削除が瞬間的ではなく、ファイルが他のプロセスによってロックされる)。
古いHDDのrimrafの60秒に対して、4,36 GBのデータ、28 042ファイル、Windowsの4 217フォルダが15秒で削除されました。
const lignator = require('lignator');
lignator.remove('./build/');
同期フォルダーは、ファイルまたはファイルのみで削除します。
私は寄付者でも寄稿者でもありませんが、この問題の適切な解決策を見つけることができなかったので、自分の方法を見つけなければなり
ませんでした。ネストされたディレクトリとサブディレクトリ。関数を再帰するときの「this」のスコープに関する注意、実装は異なる場合があります。私の場合、この関数は別の関数の戻り値にとどまるので、これを使って呼び出しています。
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);
}
一方でrecursive
の実験的なオプションであります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);
});
});
});
}
2020年の更新
バージョン12.10.0以降、オプションにrecursiveOptionが追加されました。
再帰的な削除は実験的なものであることに注意してください。
だからあなたは同期のために行うでしょう:
fs.rmdirSync(dir, {recursive: true});
または非同期の場合:
fs.rmdir(dir, {recursive: true});
rmdirモジュールを使用してください!簡単でシンプルです。
別の代替策は、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以降)が必要です
迅速かつダーティーな方法(おそらくテスト用)は、exec
またはspawn
メソッドを直接使用してOS呼び出しを呼び出し、ディレクトリを削除することです。NodeJs child_processの詳細を読んでください。
let exec = require('child_process').exec
exec('rm -Rf /tmp/*.zip', callback)
欠点は次のとおりです。
利点:
-f
安全のためにフラグを削除するか、入力中にすべてを削除しないことを確認できます。exec + rm
テスト中によく使用するノードでの有効で便利なコマンドです。
非常に微小で一般的な何かのために追加のモジュールなしでこれを行う方法があったらいいのにと思いますが、これは私が思いつくことができる最高のものです。
更新: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 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
、シェルを呼び出さないwhich を使用し、代わりに明示的に引数を渡します。
これは、promisifyと2つのヘルプ関数(toとtoAll)を使用して約束を解決する1つの方法です。
非同期ですべてのアクションを実行します。
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)
}
};
//サードパーティのlibを使用しない
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)
、フォルダー内のパスの配列の場合、反復しfs.unlink(filename)
て各ファイルfs.rmdir(dirPath)
を削除し、最後に空になったフォルダーを削除します。再帰する必要がある場合は、を確認してくださいfs.lstat(filename).isDirectory()
。