비어 있지 않은 디렉터리 제거
노드 응용 프로그램에서 일부 파일이 있지만 빈 디렉터리에서만 작동하는 디렉터리를 제거해야 합니다.어떻게 해야 하나요?
Node.js 14.14.0에서 권장되는 방법은 다음과 같습니다.
fs.rmSync(dir, { recursive: true, force: true });
.rimraf
(https://npmjs.org/package/rimraf) .와 동일한 기능을 제공합니다.rm -Rf
비동기 사용:
var rimraf = require("rimraf");
rimraf("/some/directory", function () { console.log("done"); });
동기화 사용량:
rimraf.sync("/some/directory");
폴더를 동기화하여 제거하려면
const fs = require('fs');
const Path = require('path');
const deleteFolderRecursive = function (directoryPath) {
if (fs.existsSync(directoryPath)) {
fs.readdirSync(directoryPath).forEach((file, index) => {
const curPath = path.join(directoryPath, file);
if (fs.lstatSync(curPath).isDirectory()) {
// recurse
deleteFolderRecursive(curPath);
} else {
// delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(directoryPath);
}
};
은 대분의사는자를 합니다.fs
Node.js를 사용하면 파일을 처리하는 "Unix 방식"에 가까운 기능을 사용할 수 있습니다.저는 모든 멋진 것들을 가져오기 위해 fs-extra를 사용하고 있습니다.
fs-extra에는 vanilla Node.jsfs 패키지에 포함되지 않은 메서드가 포함되어 있습니다.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);
) , Node v14 (2020년 10월) 기준,fs
모듈이 있습니다.fs.rm
그리고.rs.rmSync
recursive, 비어 있지 연결 를 지원합니다.
https://nodejs.org/docs/latest-v14.x/api/fs.html#fs_fs_rm_path_options_callback
이제 다음과 같은 작업을 수행할 수 있습니다.
const fs = require('fs');
fs.rm('/path/to/delete', { recursive: true }, () => console.log('done'));
또는:
const fs = require('fs');
fs.rmSync('/path/to/delete', { recursive: true });
console.log('done');
@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-delinked에 설명합니다.
마지막으로, 이 재귀가 실행되는 동안 이 스크립트 외부에서 항목 중 하나가 적절한 시점에 연결 해제되거나 삭제되면 재귀 오류가 발생할 수 있는 희귀한 경합 조건이 있습니다.이 시나리오는 대부분의 환경에서 일반적이지 않으므로 간과할 수 있습니다.그러나 필요한 경우(일부 에지 사례의 경우) 다음과 같은 좀 더 복잡한 예를 사용하여 이 문제를 완화할 수 있습니다.
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()
함수 합니다.끝에 있는 실제 디렉터리를 제거합니다.누락된 재귀를 수정합니다.
노드 문서에서 볼 수 있습니다.
유사한 동작을 가져오려면 다음과 같이 하십시오.
rm -rf
명령, Unix 령명, 사용 사용fs.rm()
{ recursive: true, force: true }
.
예(ESM)
import { rm } from 'node:fs/promises';
await rm('/path/to', { recursive: true, force: true });
나는 폴더 제거라는 기능을 썼습니다.위치에 있는 모든 파일과 폴더를 재귀적으로 제거합니다.그것이 필요로 하는 유일한 패키지는 비동기입니다.
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)
})
})
})
}
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);
});
});
});
};
[EDIT: node.js v15.5.0 사용]
여기에 게시된 솔루션 중 일부를 사용해 본 결과 다음과 같은 사용 중지 경고가 발생했습니다.
(노드:13202) [DEP0147] 사용 중지 경고:Node.js 이후 버전에서는 경로가 없거나 파일인 경우 fs.rmdir(경로, {recursive:true })가 느려집니다.대신 fs.rm(경로, {recursive: true, force: true }) 사용
fs.rm(path, { recursive: true, force: true });
잘작니다합과 함께 잘합니다.fs.rmSync(path, { recursive: true, force: true });
차단 버전을 사용하려는 경우.
노드 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);
}
}
const fs = require("fs");
fs.rmdir("./test", { recursive: true }, (err) => {
if (err) {
console.error(err);
}
});
을 합니다.recursive: true
그리고 경로의 합니다. ( about the pathtest
루트에 디렉터리가 있습니다.)
2020년 업데이트
버전 12.10.0부터는 옵션에 대한 recursiveOption이 추가되었습니다.
재귀 삭제는 실험적인 것입니다.
따라서 동기화를 위해 다음 작업을 수행합니다.
fs.rmdirSync(dir, {recursive: true});
또는 비동기의 경우:
fs.rmdir(dir, {recursive: true});
문서에 따르면,fsPromises
은(는) 니다합공제를현을 합니다.recursive
적어도 Windows의 경우에는 디렉터리와 그 안에 있는 모든 파일을 제거하는 실험적인 옵션입니다.
fsPromises.rmdir(path, {
recursive: true
})
있습니까?recursive: true
Linux 및 MacOS에서 파일을 제거하시겠습니까?
설명
Node에는 Node.js v14를 할 수 .require("fs").promises.rm
약속을 사용하여 파일을 제거하는 기능.첫 번째 인수는 제거할 파일 또는 폴더(존재하지 않는 파일도 포함)입니다.당신은 할 수 .recursive
그리고.force
rm
가 셸 명령 -rf
옵션들.
예
"use strict";
require("fs").promises.rm("directory", {recursive: true, force: true}).then(() => {
console.log("removed");
}).catch(error => {
console.error(error.message);
});
봐
저는 여기에 도착했습니다.gulp
더 많은 소식을 듣고 싶어서 편지를 쓰고 있습니다
gulp-clean
때문에 권장되지 않는.gulp-rimraf
gulp-rimraf
을 위해 추천되지 않는.
를 사용하여 파일 및 폴더를 삭제하려면 다음을 추가해야 합니다./**
재귀 삭제를 위해.
gulp.task('clean', function () {
return del(['some/path/to/delete/**']);
});
Node.에서는 Node.js(12.10.0)가 됩니다.rmdir
스타일 함수 , 및 새 실험 옵션이 있습니다.recursive
비어 있지 않은 디렉터리를 삭제할 수 있습니다.
fs.rmdir(path, { recursive: true });
GitHub 관련 홍보: https://github.com/nodejs/node/pull/29168
fs.promise를 사용한 @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);
}
};
에는 "/기다리다"를 할 수 .fs/promises
API.API.
const fs = require('fs/promises');
const removeDir = async (dirPath) => {
await fs.rm(dirPath, {recursive: true});
}
폴더에 있는 단일 파일의 경로를 알고 해당 파일이 들어 있는 폴더를 삭제하려는 경우.
const fs = require('fs/promises');
const path = require('path');
const removeDir = async (filePath) => {
const { dir } = path.parse(filePath);
await fs.rm(dir, { recursive: true });
}
return new Promise((resolve, reject) => {
const fs = require("fs");
// directory path
const dir = "your/dir";
// delete directory recursively <------
fs.rmdir(dir, { recursive: true }, (err) => {
if (err) {
reject(err);
}
resolve(`${dir} is deleted!`);
});
});
그냥 usermdir module! 쉽고 간단합니다.
빠르고 더러운 방법(테스트용일 수 있음)은 직접 사용할 수 있습니다.exec
또는spawn
OS 호출을 호출하여 디렉터리를 제거하는 메서드입니다.NodeJs child_process에 대해 자세히 알아보십시오.
let exec = require('child_process').exec
exec('rm -Rf /tmp/*.zip', callback)
단점은 다음과 같습니다.
- 기본 OS에 의존합니다. 즉, 동일한 방법이 unix/linux에서 실행되지만 Windows에서는 실행되지 않을 수 있습니다.
- 조건이나 오류가 발생한 경우 프로세스를 하이잭할 수 없습니다.기본 OS에 작업을 부여하고 종료 코드가 반환될 때까지 기다립니다.
이점:
- 이러한 프로세스는 비동기적으로 실행될 수 있습니다.
- 명령의 출력/오류를 수신할 수 있으므로 명령 출력이 손실되지 않습니다.작업이 완료되지 않은 경우 오류 코드를 확인하고 다시 시도할 수 있습니다.
는 사상의패는입니다.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))
}
비동기식 접근법에서, 비어있지 않은 dir를 삭제하기 위해서는
rmdir(path,{recursive:true,force:true}
rm(path,{recursive:true,force:true}
효과가 있을 것
코드 조각:
const fsp = require("fs/promises");
deleteDirRecursively("./b");
removeRecursively("./BCD/b+");
async function deleteDirRecursively(dirPath) {
try {
// fsPromises.rmdir() on a file (not a directory) results in the promise being rejected
// with an ENOENT error on Windows and an ENOTDIR error on POSIX.
// To get a behavior similar to the rm -rf Unix command,
// use fsPromises.rm() with options { recursive: true, force: true }.
//will not thorw error if dir is empty
//will thow error if dir is not present
await fsp.rmdir(dirPath, { recursive: true, force: true });
console.log(dirPath, "deleted successfully");
} catch (err) {
console.log(err);
}
async function removeRecursively(path) {
try {
//has ability to remove both file and dir
//can delete dir recursively and forcefully
//will delete an empty dir.
//will remove all the contents of a dir.
// the only difference between rmdir and rm is that rmdir can only delete dir's
await fsp.rm(path, { recursive: true, force: true });
console.log(path, "deleted successfully");
} catch (err) {
console.log(err);
}
}
초고속 및 장애 방지
당신은 할 수 .lignator
package(https://www.npmjs.com/package/lignator), 는 어떤 비동기 코드(예: rimraf)보다 빠르고 장애 방지 기능이 뛰어납니다(특히 파일 제거가 즉각적으로 이루어지지 않고 다른 프로세스에 의해 파일이 잠길 수 있는 Windows의 경우).
이전 HDD에서 Rimraf의 60초에 비해 Windows에서 4,36GB의 데이터, 28042개의 파일, 4217개의 폴더가 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);
}
2020년 정답
npm 스크립트에서 이 작업을 수행하려면 다음 명령을 사용할 경우 타사 패키지를 미리 설치할 필요가 없습니다.npx
예를 들어, 를 실행할 때 dist 및 .cache 폴더를 삭제하려는 경우npm run clean
그런 다음 이 명령을 패키지에 추가합니다.제이손
{
"scripts": {
"clean": "npx rimraf dist .cache"
}
}
모든 작동 시스템에서 작동합니다.
또 다른 대안은 약속된 버전의 모듈을 제공하는 모듈을 사용하는 것입니다.
그런 다음 다음 다음과 같이 쓸 수 있습니다.
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)
참고: 비동기/동기화를 사용하려면 최신 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 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);
});
}
언급URL : https://stackoverflow.com/questions/18052762/remove-directory-which-is-not-empty
'programing' 카테고리의 다른 글
여러 원격 위치에서 풀/푸시하려면 어떻게 해야 합니까? (0) | 2023.05.16 |
---|---|
Python 목록에서 인접한 항목 쌍을 통해 반복 (0) | 2023.05.16 |
MVVM Light Toolkit 샘플 (0) | 2023.05.16 |
Visual Studio에서 프로젝트/솔루션 간에 코드를 공유하는 방법은 무엇입니까? (0) | 2023.05.16 |
Git의 사인 오프 기능은 무엇을 위한 것입니까? (0) | 2023.05.16 |