83

fs.rmdirのドキュメントは非常に短く、ディレクトリが空でない場合の rmdir の動作について説明していません。

Q : この API を使用して空でないディレクトリを削除しようとするとどうなりますか?

4

23 に答える 23

59

私はこの問題について正確に書きました。

以下の私の以前の解決策は単純ですが、好まれません。次の関数は同期ソリューションです。async が優先される場合があります。

deleteFolderRecursive = function(path) {
    var files = [];
    if( fs.existsSync(path) ) {
        files = fs.readdirSync(path);
        files.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);
    }
};

[編集]シンボリックリンクのエラーを防ぐために stat の代わりに lstat を追加

[以前の解決策]

これに対する私の解決策は、実装が非常に簡単です。

var exec = require('child_process').exec,child;
child = exec('rm -rf test',function(err,out) { 
  console.log(out); err && console.log(err); 
});

このページではこれを簡略化していますが、基本的な考え方は単純です。コマンドラインで「rm -r」を実行します。アプリをさまざまな種類の OS で実行する必要がある場合は、これを関数に入れ、それを処理する if/else/switch を用意します。

すべての応答を処理する必要があります。しかし、アイデアは十分に単純です。

于 2012-10-06T17:09:48.880 に答える
38

簡単な答え: node.js fs.rmdir()は POSIX を呼び出しrmdir()ます。これにより、空のディレクトリが削除されるか、エラーが返されます。特定のケースでは、コールはコールバック関数を呼び出し、エラーを例外として渡します。

ここでの問題は、node.js のドキュメントがPOSIXを参照していることです。

Node.js API Docs File System API は、

標準 POSIX 関数の単純なラッパー。

これは、質問を次の複製にほとんど変更します: Is there a list of the POSIX API / functions?

の説明fs.rmdirは簡潔ですが、十分です。

非同期 rmdir(2)。

here は、のrmdir(2)ドキュメントへの暗黙的な参照rmdir() system callです。ここでの番号 (2) は、カーネル インターフェイスを含むマニュアル ページのセクション 2 を示す古い UNIX マニュアル ページの規則です。

于 2012-09-27T23:19:47.997 に答える
22

Node.js v12.10.0 で にrecursiveオプションが導入されましたfs.rmdir。v10.12.0fs.mkdirから同じオプションをサポートしているため、ディレクトリの作成と削除の両方を再帰的に実行できます。

$ node --experimental-repl-await

# without recursive option -> error
> await fs.promises.mkdir('foo/bar')
Thrown:
[Error: ENOENT: no such file or directory, mkdir 'foo/bar'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'mkdir',
  path: 'foo/bar'
}

# with recursive option -> success
> await fs.promises.mkdir('foo/bar', { recursive: true })
undefined

# without recursive option -> error
> await fs.promises.rmdir('foo')
Thrown:
[Error: ENOTEMPTY: directory not empty, rmdir 'foo'] {
  errno: -66,
  code: 'ENOTEMPTY',
  syscall: 'rmdir',
  path: 'foo'
}

# with recursive option -> success
> await fs.promises.rmdir('foo', { recursive: true })
undefined
于 2019-09-05T12:19:22.847 に答える
11

これは私のために働いた

fs.rmdirSync(folderpath, {recursive: true});

編集 2021:

現在、v14 で次のように置き換えられているようです。

fs.rmSync('./output', {recursive: true, force: true});
于 2020-07-17T14:51:21.417 に答える
5

fs.rmdir再帰的ではありません。

代わりに、 readdirpのような再帰的な fs.readdir モジュールを使用して、すべてのファイルとディレクトリを見つけることができます。次に、すべてのファイルを削除し、続いてすべてのディレクトリを削除します。

さらに簡単な解決策については、rimrafをご覧ください。

于 2012-09-27T20:57:21.560 に答える
3

より高速なchild_process.execFile を使用してください。

NodeJS ドキュメント:

child_process.execFile は child_process.exec() と似ていますが、サブシェルを実行するのではなく、指定されたファイルを直接実行します。

これは機能します。模倣rm -rf DIR...

var child = require('child_process');

var rmdir = function(directories, callback) {
    if(typeof directories === 'string') {
        directories = [directories];
    }
    var args = directories;
    args.unshift('-rf');
    child.execFile('rm', args, {env:process.env}, function(err, stdout, stderr) {
            callback.apply(this, arguments);
    });
};

// USAGE
rmdir('dir');
rmdir('./dir');
rmdir('dir/*');
rmdir(['dir1', 'dir2']);

編集:これはクロスプラットフォームではなく、Windowsでは機能しないことを認めなければなりません

于 2013-05-04T17:03:14.467 に答える
2

これは、promise で動作する非同期再帰バージョンです。私は 'Q' ライブラリを使用していますが、いくつかの変更 ('fail' 関数など) は誰でもできます。

それを利用するには、いくつかのコア Node 関数、つまり fs.stat、fs.readdir、fs.unlink、fs.rmdir の周りにいくつかの単純なラッパーを作成して、promise フレンドリーにする必要があります。

どうぞ:

function getStat(fpath) {
  var def = Q.defer();
  fs.stat(fpath, function(e, stat) {
    if (e) { def.reject(); } else { def.resolve(stat); }
  });
  return def.promise;
}

function readdir(dirpath) {
  var def = Q.defer();
  fs.readdir(dirpath, function(e, files) {
    if (e) { def.reject(e); } else { def.resolve(files); }
  });
  return def.promise;
}

function rmFile(fpath) {
  var def = Q.defer();
  fs.unlink(fpath, function(e) { if(e) { def.reject(e); } else { def.resolve(fpath); }});
  return def.promise;
}

function rmDir(fpath) {
  var def = Q.defer(); 
  fs.rmdir(fpath, function(e) { if(e) { def.reject(e); } else { def.resolve(fpath); }});
  return def.promise;
}

したがって、再帰的な rm 関数は次のとおりです。

var path = require('path');

function recursiveDelete(fpath) {
  var def = Q.defer();

  getStat(fpath)
  .then(function(stat) {
    if (stat.isDirectory()) {
      return readdir(fpath)
      .then(function(files) {
        if (!files.length) { 
          return rmDir(fpath);
        } else {
          return Q.all(files.map(function(f) { return recursiveDelete(path.join(fpath, f)); }))
          .then(function() { return rmDir(fpath); });
        }
      }); 
    } else {
      return rmFile(fpath);
    }
  })
  .then(function(res) { def.resolve(res); })
  .fail(function(e) { def.reject(e); })
  .done();
  return def.promise;
}
于 2013-10-16T19:32:00.520 に答える
1

これは当面の質問に正確に答えているわけではないことは承知していますが、これは将来ここを検索する人にとって役立つかもしれないと思います (それは私にとってだったでしょう!) :ディレクトリ. ディレクトリ (またはその子孫ディレクトリのいずれか) にコンテンツが含まれている場合、それはそのまま残されます。

var fs = require("fs");
var path = require("path");

var rmdir = function(dir) {
    var empty = true, list = fs.readdirSync(dir);
    for(var i = list.length - 1; i >= 0; i--) {
        var filename = path.join(dir, list[i]);
        var stat = fs.statSync(filename);

        if(filename.indexOf('.') > -1) {
            //There are files in the directory - we can't empty it!
            empty = false;
            list.splice(i, 1);
        }
    }

    //Cycle through the list of sub-directories, cleaning each as we go
    for(var i = list.length - 1; i >= 0; i--) {
        filename = path.join(dir, list[i]);
        if (rmdir(filename)) {
            list.splice(i, 1);
        }
    }

    //Check if the directory was truly empty
    if (!list.length && empty) {
        console.log('delete!');
        fs.rmdirSync(dir);
        return true;
    }
    return false;
};

https://gist.github.com/azaslavsky/661020d437fa199e95ab

于 2014-05-13T22:35:39.150 に答える
1

これは、ソースに飛び込むための良い言い訳だと思いました ;)

私が知る限りfs.rmdir、unistd.h の rmdir 関数にバインドされています。rmdirの POSIX man ページから:

rmdir() 関数は、パスで指定された名前のディレクトリを削除します。ディレクトリは、空のディレクトリである場合にのみ削除されます。

ディレクトリが空のディレクトリでない場合、rmdir() は失敗し、errno を [EEXIST] または [ENOTEMPTY] に設定します。

于 2012-09-27T19:56:52.460 に答える
1

空でないディレクトリを同期的に削除する:-

以下はファイル構造です -

ここに画像の説明を入力

var fs = require('fs');

fs.unlink('./stuff/writeMe.txt',function(){
  fs.rmdirSync('stuff');
})

まず、 stuffフォルダーを空にするコードを使用して、 stuffフォルダーからwriteMe.txtファイルを削除し、最後にコードを使用して削除します。 fs.unlink('./stuff/writeMe.txt')fs.rmdirSync('stuff')

于 2021-01-16T10:31:55.747 に答える
1

正しい「いいえ」の答えに加えて、rimrafパッケージは再帰的な削除機能を提供します。それは模倣しrm -rfます。また、Ubuntu によって公式にパッケージ化されています。

于 2013-03-29T18:07:19.973 に答える
0

これは、フォルダーを再帰的に削除するfluentnode用に作成したコーヒー スクリプトのプロトタイプ関数です。

String::folder_Delete_Recursive = ->
  path = @.toString()
  if path.exists()
    for file in path.files()
      curPath = path.path_Combine(file)
      if curPath.is_Folder()
        curPath.folder_Delete_Recursive()
      else
        curPath.file_Delete()
    fs.rmdirSync(path);

  return path.not_Exists()

ここにテストがあります:

it 'folder_Create and folder_Delete' , ->
  tmpDir = "./".temp_Name_In_Folder()
  expect(tmpDir.folder_Exists()).to.be.false
  expect(tmpDir.folder_Create()).to.equal(tmpDir.realPath())
  expect(tmpDir.folder_Exists()).to.be.true
  expect(tmpDir.folder_Delete()).to.be.true
  expect(tmpDir.folder_Exists()).to.be.false

it 'folder_Delete_Recursive' , ->
  tmpDir = "./"   .temp_Name_In_Folder().folder_Create()
  tmpFile = tmpDir.temp_Name_In_Folder().file_Create()
  expect(tmpDir.folder_Delete_Recursive()).to.be.true
于 2014-10-22T08:09:01.790 に答える
0

この関数は、指定したディレクトリまたはファイルを同期的に再帰的に削除します。

var path = require('path');

function deleteRecursiveSync(itemPath) {
    if (fs.statSync(itemPath).isDirectory()) {
        _.each(fs.readdirSync(itemPath), function(childItemName) {
            deleteRecursiveSync(path.join(itemPath, childItemName));
        });
        fs.rmdirSync(itemPath);
    } else {
        fs.unlinkSync(itemPath);
    }
}

次の場合、この関数の動作をテストしていません。

  • アイテムが存在しない、または
  • アイテムを削除できません (権限の問題などにより)。
于 2013-10-29T15:39:31.963 に答える
0

この投稿はGoogleからトップの回答を得ていましたが、どの回答も次のような解決策を提供していません:

  • 同期機能を利用しない

  • 外部ライブラリを必要としません

  • bash を直接使用しない

asyncノードがインストールされていること以外は何も想定していない私のソリューションは次のとおりです。

const fs = require('fs'); const path = require('path');

function rm(path){  
    return stat(path).then((_stat) => {                                   

    if(_stat.isDirectory()){                                                                                                                                                                                                                          
      return ls(path)                                                                                                                                                                                                                                   
        .then((files) => Promise.all(files.map(file => rm(Path.join(path, file)))))
       .then(() => removeEmptyFolder(path));                                                                                                                                                                                                 
    }else{                                                                                                                                                                                                                                            
      return removeFileOrLink(path);                                                                                                                                                                                                            
    }   });
                                                                                                                                                                                                                                              function removeEmptyFolder(path){                                     

    return new Promise((done, err) => {                                                                                                                                                                                                               
      fs.rmdir(path, function(error){                                                                                                                                                                                                                   
        if(error){ return err(error); }                                                                                                                                                                                                               
        return done("ok");                                                                                                                                                                                                                        
      });                                                                                                                                                                                                                                       
    });                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                function removeFileOrLink(path){                                      

    return new Promise((done, err) => {                                                                                                                                                                                                               
      fs.unlink(path, function(error){                                                                                                                                                                                                                  
        if(error){ return err(error); }                                                                                                                                                                                                               
        return done("ok");                                                                                                                                                                                                                        
      });                                                                                                                                                                                                                                       
    });                                                                                                                                                                                                                                          }

                                                                                                                                                                                                                                                function ls(path){                                                    

    return new Promise((done, err) => {                                                                                                                                                                                                               
      fs.readdir(path, function (error, files) {                                                                                                                                                                                                        
        if(error) return err(error)                                                                                                                                                                                                                   
        return done(files)                                                                                                                                                                                                                        
      });                                                                                                                                                                                                                                       
    });                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                function stat(path){                                                  

    return new Promise((done, err) => {                                                                                                                                                                                                               
      fs.stat(path, function (error, _stat) {                                                                                                                                                                                                           
        if(error){ return err(error); }                                                                                                                                                                                                               
        return done(_stat);                                                                                                                                                                                                                       
      });                                                                                                                                                                                                                                       
    });                                                                                                                                                                                                                                          } }
于 2017-06-26T14:12:17.257 に答える
0

rmdirSync のきちんとした同期バージョン。

/** 
 * use with try ... catch ...
 * 
 * If you have permission to remove all file/dir
 * and no race condition and no IO exception...
 * then this should work 
 *
 * uncomment the line 
 *   if(!fs.exists(p)) return 
 * if you care the inital value of dir, 
 * 
 */
var fs = require('fs')
var path = require('path')

function rmdirSync(dir,file){
  var p = file? path.join(dir,file):dir;
  // if(!fs.exists(p)) return 
  if(fs.lstatSync(p).isDirectory()){
    fs.readdirSync(p).forEach(rmdirSync.bind(null,p))
    fs.rmdirSync(p)
  }
  else fs.unlinkSync(p)
}

パラレル IO、非同期バージョンの rmdir。(もっと早く)

/**
 * NOTE: 
 * 
 * If there are no error, callback will only be called once.
 * 
 * If there are multiple errors, callback will be called 
 * exactly as many time as errors occur. 
 * 
 * Sometimes, this behavior maybe useful, but users 
 * should be aware of this and handle errors in callback. 
 * 
 */

var fs = require('fs')
var path = require('path')

function rmfile(dir, file, callback){
  var p = path.join(dir, file)
  fs.lstat(p, function(err, stat){
    if(err) callback.call(null,err)
    else if(stat.isDirectory()) rmdir(p, callback)
    else fs.unlink(p, callback)
  })
}

function rmdir(dir, callback){
  fs.readdir(dir, function(err,files){
    if(err) callback.call(null,err)
    else if( files.length ){
      var i,j
      for(i=j=files.length; i--; ){
        rmfile(dir,files[i], function(err){
          if(err) callback.call(null, err)
          else if(--j === 0 ) fs.rmdir(dir,callback)
        })
      }
    }
    else fs.rmdir(dir, callback)
  })
}

とにかく、シーケンシャル IO が必要な場合は、コールバックを 1 回だけ呼び出します (成功または最初のエラーが発生した場合)。この rmdir を上記のものに置き換えます。(もっとゆっくり)

function rmdir(dir, callback){
  fs.readdir(dir, function(err,files){
    if(err) callback.call(null,err)
    else if( files.length ) rmfile(dir, files[0], function(err){
      if(err) callback.call(null,err)
      else rmdir(dir, callback)
    })
    else fs.rmdir(dir, callback)
  })
}

それらはすべてnode.jsのみに依存しており、移植可能である必要があります。

于 2014-11-06T12:56:33.547 に答える