2013-08-05 3 views

ответ

125

Существует модуль для этого: rimraf (https://npmjs.org/package/rimraf). Она обеспечивает такую ​​же функциональность как rm -Rf

Основное использование:

var rimraf = require('rimraf'); 
rimraf('/some/directory', function() { console.log('done'); }); 
+15

Существует также синхронная версия: rimraf.sync ('/ некоторые/каталог '); –

8

Я написал эту функцию, называемую папку удалить. Он будет рекурсивно удалять все файлы и папки в определенном месте. Единственный требуемый пакет - асинхронный.

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) 
      }) 
     }) 
    }) 
} 
+2

Идея состоит в том, чтобы не писать собственный код, если он уже написан кем-то другим. Лучший способ сделать это - использовать rimraf или fs-extra или любой другой модуль узла, чтобы выполнить эту работу для вас. –

+62

Да, писать собственный код ужасно, потому что использование десятков сторонних модулей для относительно тривиальных операций никогда не оказывало каких-либо недостатков в крупномасштабных приложениях. – Eric

+14

@ Эрик - подумал, что вам понравится напоминать о вашем комментарии после феномена «левого пэда» »! –

83

Чтобы удалить папку, синхронно

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); 
    } 
}; 
+11

Возможно, вы захотите добавить некоторые проверки, которые вы не собираетесь случайно запускать в '/'. Например, передача пустого пути и опечатка в файле может привести к тому, что curPath будет корневым. –

+1

Более надежная реализация: замените «var curPath = path +»/«+ file;» с помощью var varPath = p.join (путь, файл); 'если вы включили модуль пути:' var p = require ("path") ' – Andry

+1

Windows имеет \ slashes, поэтому' путь.join (dirpath, file) 'должен быть лучше, чем' path + "/" + file' – thybzi

0

Просто используйте rmdir module! это легко и просто.

+2

Не всегда полезно использовать модуль для каждой небольшой части кода. Если вам нужно создать лицензионное соглашение, например, это создает настоящую боль. – Mijago

+2

вам нужно добавить образец кода для вашего ответа, чтобы быть более интересным – Xeltor

1

Я достиг здесь, пытаясь перебраться с gulp, и я пишу для дальнейших целей.

Если вы хотите удалить файлы и папки с помощью del, вы должны добавить /** для рекурсивного удаления.

gulp.task('clean', function() { 
    return del(['some/path/to/delete/**']); 
}); 
49

Большинство людей, использующих 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') 
+6

, а затем ... 'fs.removeSync ('/ tmp/myFolder');' или 'fs.remove ('/ tmp/myFolder', callback) ; ' –

-1

с использованием 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); 
}; 
+0

Зачем расширять объект? – programmer5000

+0

Нет, извините, это не намерение. это скорее местозаполнитель того, что когда-либо было вашим объектом. я отредактирую его @ programmer5000 –

+2

Зачем расширять * любой * объект? – programmer5000

0

Я хотел было способ сделать это без дополнительных модулей для чего-то столь крохотного и общего, но это лучшее, что я мог придумать.

Обновление: Должно быть теперь работать с 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); 
    }); 
} 
+0

Возможно, fs-extra's - это путь, если вы хотите использовать один модуль. – b01

+0

Зачем голосовать за этот ответ? Он исправляет – Gabriel

+0

@ Gabriel, потому что он предназначен только для систем * nix/Linux. Команды over shell/exec не масштабируются. –

8

Вот версия асинхронной из @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); 
      }); 
     }); 
    }); 
}; 
8

Мой модифицированном ответ от @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); 
    } 
} 
0

Другой альтернативой является использование модуля 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+)

1

версия 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)) 
} 
0

быстрый и грязный способ (возможно, для тестирования) может быть непосредственно использовать exec или spawn метод для вызова вызова ОС для удаления каталога. Подробнее о NodeJs child_process.

let exec = require('child_process').exec 
exec('rm -Rf /tmp/*.zip', callback) 

Downsides являются:

  1. Вы в зависимости от базовой ОС т.е. тот же метод будет работать в Unix/Linux, но, вероятно, не в окнах.
  2. Вы не можете захватить процесс на условиях или ошибках. Вы просто отдаете задачу базовой ОС и ждете возврата кода выхода.

Преимущества:

  1. Эти процессы могут выполняться асинхронно.
  2. Вы можете прослушивать вывод/ошибку команды, поэтому вывод команды не теряется. Если операция не завершена, вы можете проверить код ошибки и повторить попытку.
0

Если вы используете узел 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}`); 
    } 
} 
Смежные вопросы