4 `fs-extra` adds file system methods that aren't included in the native `fs` module. It is a drop in replacement for `fs`.
6 [![npm Package](https://img.shields.io/npm/v/fs-extra.svg?style=flat-square)](https://www.npmjs.org/package/fs-extra)
7 [![build status](https://api.travis-ci.org/jprichardson/node-fs-extra.svg)](http://travis-ci.org/jprichardson/node-fs-extra)
8 [![windows Build status](https://img.shields.io/appveyor/ci/jprichardson/node-fs-extra/master.svg?label=windows%20build)](https://ci.appveyor.com/project/jprichardson/node-fs-extra/branch/master)
9 [![downloads per month](http://img.shields.io/npm/dm/fs-extra.svg)](https://www.npmjs.org/package/fs-extra)
10 [![Coverage Status](https://img.shields.io/coveralls/jprichardson/node-fs-extra.svg)](https://coveralls.io/r/jprichardson/node-fs-extra)
12 <a href="https://github.com/feross/standard"><img src="https://cdn.rawgit.com/feross/standard/master/sticker.svg" alt="Standard JavaScript" width="100"></a>
14 **NOTE (2016-11-01):** Node v0.12 will be unsupported on 2016-12-31.
20 I got tired of including `mkdirp`, `rimraf`, and `ncp` in most of my projects.
28 npm install --save fs-extra
35 `fs-extra` is a drop in replacement for native `fs`. All methods in `fs` are unmodified and attached to `fs-extra`.
37 You don't ever need to include the original `fs` module again:
40 var fs = require('fs') // this is no longer necessary
46 var fs = require('fs-extra')
49 or if you prefer to make it clear that you're using `fs-extra` and not `fs`, you may want
50 to name your `fs` variable `fse` like so:
53 var fse = require('fs-extra')
56 you can also keep both, but it's redundant:
59 var fs = require('fs')
60 var fse = require('fs-extra')
65 Most methods are async by default (they take a callback with an `Error` as first argument).
67 Sync methods on the other hand will throw if an error occurs.
72 var fs = require('fs-extra')
74 fs.copy('/tmp/myfile', '/tmp/mynewfile', function (err) {
75 if (err) return console.error(err)
76 console.log("success!")
80 fs.copySync('/tmp/myfile', '/tmp/mynewfile')
81 console.log("success!")
92 - [emptyDir](#emptydirdir-callback)
93 - [emptyDirSync](#emptydirdir-callback)
94 - [ensureFile](#ensurefilefile-callback)
95 - [ensureFileSync](#ensurefilefile-callback)
96 - [ensureDir](#ensuredirdir-callback)
97 - [ensureDirSync](#ensuredirdir-callback)
98 - [ensureLink](#ensurelinksrcpath-dstpath-callback)
99 - [ensureLinkSync](#ensurelinksrcpath-dstpath-callback)
100 - [ensureSymlink](#ensuresymlinksrcpath-dstpath-type-callback)
101 - [ensureSymlinkSync](#ensuresymlinksrcpath-dstpath-type-callback)
102 - [mkdirs](#mkdirsdir-callback)
103 - [mkdirsSync](#mkdirsdir-callback)
104 - [move](#movesrc-dest-options-callback)
105 - [outputFile](#outputfilefile-data-options-callback)
106 - [outputFileSync](#outputfilefile-data-options-callback)
107 - [outputJson](#outputjsonfile-data-options-callback)
108 - [outputJsonSync](#outputjsonfile-data-options-callback)
109 - [readJson](#readjsonfile-options-callback)
110 - [readJsonSync](#readjsonfile-options-callback)
111 - [remove](#removedir-callback)
112 - [removeSync](#removedir-callback)
114 - [walkSync](#walkSyncDir)
115 - [writeJson](#writejsonfile-object-options-callback)
116 - [writeJsonSync](#writejsonfile-object-options-callback)
119 **NOTE:** You can still use the native Node.js methods. They are copied over to `fs-extra`.
124 **copy(src, dest, [options], callback)**
127 Copy a file or directory. The directory can have contents. Like `cp -r`.
130 - clobber (boolean): overwrite existing file or directory, default is `true`.
131 - dereference (boolean): dereference symlinks, default is `false`.
132 - preserveTimestamps (boolean): will set last modification and access times to the ones of the original source files, default is `false`.
133 - filter: Function to filter copied files. Return `true` to include, `false` to exclude. This can also be a RegExp, however this is deprecated (See [issue #239](https://github.com/jprichardson/node-fs-extra/issues/239) for background). _Warning: `copySync` currently applies the filter only to files (see [#180](https://github.com/jprichardson/node-fs-extra/issues/180)). This will be fixed in a future release._
140 var fs = require('fs-extra')
142 fs.copy('/tmp/myfile', '/tmp/mynewfile', function (err) {
143 if (err) return console.error(err)
144 console.log("success!")
147 fs.copy('/tmp/mydir', '/tmp/mynewdir', function (err) {
148 if (err) return console.error(err)
149 console.log('success!')
150 }) // copies directory, even if it has subdirectories or files
154 ### emptyDir(dir, [callback])
156 Ensures that a directory is empty. Deletes directory contents if the directory is not empty. If the directory does not exist, it is created. The directory itself is not deleted.
160 Sync: `emptyDirSync()`, `emptydirSync()`
165 var fs = require('fs-extra')
167 // assume this directory has a lot of files and folders
168 fs.emptyDir('/tmp/some/dir', function (err) {
169 if (!err) console.log('success!')
174 ### ensureFile(file, callback)
176 Ensures that the file exists. If the file that is requested to be created is in directories that do not exist, these directories are created. If the file already exists, it is **NOT MODIFIED**.
178 Alias: `createFile()`
180 Sync: `createFileSync()`,`ensureFileSync()`
186 var fs = require('fs-extra')
188 var file = '/tmp/this/path/does/not/exist/file.txt'
189 fs.ensureFile(file, function (err) {
190 console.log(err) // => null
191 // file has now been created, including the directory it is to be placed in
196 ### ensureDir(dir, callback)
198 Ensures that the directory exists. If the directory structure does not exist, it is created.
200 Sync: `ensureDirSync()`
206 var fs = require('fs-extra')
208 var dir = '/tmp/this/path/does/not/exist'
209 fs.ensureDir(dir, function (err) {
210 console.log(err) // => null
211 // dir has now been created, including the directory it is to be placed in
216 ### ensureLink(srcpath, dstpath, callback)
218 Ensures that the link exists. If the directory structure does not exist, it is created.
220 Sync: `ensureLinkSync()`
226 var fs = require('fs-extra')
228 var srcpath = '/tmp/file.txt'
229 var dstpath = '/tmp/this/path/does/not/exist/file.txt'
230 fs.ensureLink(srcpath, dstpath, function (err) {
231 console.log(err) // => null
232 // link has now been created, including the directory it is to be placed in
237 ### ensureSymlink(srcpath, dstpath, [type], callback)
239 Ensures that the symlink exists. If the directory structure does not exist, it is created.
241 Sync: `ensureSymlinkSync()`
247 var fs = require('fs-extra')
249 var srcpath = '/tmp/file.txt'
250 var dstpath = '/tmp/this/path/does/not/exist/file.txt'
251 fs.ensureSymlink(srcpath, dstpath, function (err) {
252 console.log(err) // => null
253 // symlink has now been created, including the directory it is to be placed in
258 ### mkdirs(dir, callback)
260 Creates a directory. If the parent hierarchy doesn't exist, it's created. Like `mkdir -p`.
264 Sync: `mkdirsSync()` / `mkdirpSync()`
270 var fs = require('fs-extra')
272 fs.mkdirs('/tmp/some/long/path/that/prob/doesnt/exist', function (err) {
273 if (err) return console.error(err)
274 console.log("success!")
277 fs.mkdirsSync('/tmp/another/path')
281 ### move(src, dest, [options], callback)
283 Moves a file or directory, even across devices.
286 - clobber (boolean): overwrite existing file or directory
287 - limit (number): number of concurrent moves, see ncp for more information
292 var fs = require('fs-extra')
294 fs.move('/tmp/somefile', '/tmp/does/not/exist/yet/somefile', function (err) {
295 if (err) return console.error(err)
296 console.log("success!")
301 ### outputFile(file, data, [options], callback)
303 Almost the same as `writeFile` (i.e. it [overwrites](http://pages.citebite.com/v2o5n8l2f5reb)), except that if the parent directory does not exist, it's created. `options` are what you'd pass to [`fs.writeFile()`](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback).
305 Sync: `outputFileSync()`
311 var fs = require('fs-extra')
312 var file = '/tmp/this/path/does/not/exist/file.txt'
314 fs.outputFile(file, 'hello!', function (err) {
315 console.log(err) // => null
317 fs.readFile(file, 'utf8', function (err, data) {
318 console.log(data) // => hello!
325 ### outputJson(file, data, [options], callback)
327 Almost the same as `writeJson`, except that if the directory does not exist, it's created.
328 `options` are what you'd pass to [`jsonFile.writeFile()`](https://github.com/jprichardson/node-jsonfile#writefilefilename-options-callback).
330 Alias: `outputJSON()`
332 Sync: `outputJsonSync()`, `outputJSONSync()`
338 var fs = require('fs-extra')
339 var file = '/tmp/this/path/does/not/exist/file.txt'
341 fs.outputJson(file, {name: 'JP'}, function (err) {
342 console.log(err) // => null
344 fs.readJson(file, function(err, data) {
345 console.log(data.name) // => JP
352 ### readJson(file, [options], callback)
354 Reads a JSON file and then parses it into an object. `options` are the same
355 that you'd pass to [`jsonFile.readFile`](https://github.com/jprichardson/node-jsonfile#readfilefilename-options-callback).
359 Sync: `readJsonSync()`, `readJSONSync()`
365 var fs = require('fs-extra')
367 fs.readJson('./package.json', function (err, packageObj) {
368 console.log(packageObj.version) // => 0.1.3
372 `readJsonSync()` can take a `throws` option set to `false` and it won't throw if the JSON is invalid. Example:
375 var fs = require('fs-extra')
376 var file = path.join('/tmp/some-invalid.json')
377 var data = '{not valid JSON'
378 fs.writeFileSync(file, data)
380 var obj = fs.readJsonSync(file, {throws: false})
381 console.log(obj) // => null
385 ### remove(dir, callback)
387 Removes a file or directory. The directory can have contents. Like `rm -rf`.
395 var fs = require('fs-extra')
397 fs.remove('/tmp/myfile', function (err) {
398 if (err) return console.error(err)
400 console.log('success!')
403 fs.removeSync('/home/jprichardson') //I just deleted my entire HOME directory.
408 **walk(dir, [streamOptions])**
410 The function `walk()` from the module [`klaw`](https://github.com/jprichardson/node-klaw).
412 Returns a [Readable stream](https://nodejs.org/api/stream.html#stream_class_stream_readable) that iterates
413 through every file and directory starting with `dir` as the root. Every `read()` or `data` event
414 returns an object with two properties: `path` and `stats`. `path` is the full path of the file and
415 `stats` is an instance of [fs.Stats](https://nodejs.org/api/fs.html#fs_class_fs_stats).
417 Streams 1 (push) example:
420 var fs = require('fs-extra')
421 var items = [] // files, directories, symlinks, etc
423 .on('data', function (item) {
424 items.push(item.path)
426 .on('end', function () {
427 console.dir(items) // => [ ... array of files]
431 Streams 2 & 3 (pull) example:
434 var items = [] // files, directories, symlinks, etc
435 var fs = require('fs-extra')
437 .on('readable', function () {
439 while ((item = this.read())) {
440 items.push(item.path)
443 .on('end', function () {
444 console.dir(items) // => [ ... array of files]
448 If you're not sure of the differences on Node.js streams 1, 2, 3 then I'd
449 recommend this resource as a good starting point: https://strongloop.com/strongblog/whats-new-io-js-beta-streams3/.
451 **See [`klaw` documentation](https://github.com/jprichardson/node-klaw) for more detailed usage.**
455 Lists all files inside a directory recursively
460 var fs = require('fs-extra')
462 var files = fs.walkSync('/home/jprichardson')
463 // files = ['/home/jprichardson/file1', '/home/jprichardson/dir1/file2']
466 ### writeJson(file, object, [options], callback)
468 Writes an object to a JSON file. `options` are the same that
469 you'd pass to [`jsonFile.writeFile()`](https://github.com/jprichardson/node-jsonfile#writefilefilename-options-callback).
473 Sync: `writeJsonSync()`, `writeJSONSync()`
478 var fs = require('fs-extra')
479 fs.writeJson('./package.json', {name: 'fs-extra'}, function (err) {
490 Use [Bluebird](https://github.com/petkaantonov/bluebird). See https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification. `fs-extra` is
491 explicitly listed as supported.
494 var Promise = require('bluebird')
495 var fs = Promise.promisifyAll(require('fs-extra'))
498 Or you can use the package [`fs-extra-promise`](https://github.com/overlookmotel/fs-extra-promise) that marries the two together.
503 If you like TypeScript, you can use `fs-extra` with it: https://github.com/borisyankov/DefinitelyTyped/tree/master/fs-extra
506 ### File / Directory Watching
508 If you want to watch for changes to files or directories, then you should use [chokidar](https://github.com/paulmillr/chokidar).
513 - [mfs](https://github.com/cadorn/mfs) - Monitor your fs-extra calls.
520 Wanna hack on `fs-extra`? Great! Your help is needed! [fs-extra is one of the most depended upon Node.js packages](http://nodei.co/npm/fs-extra.png?downloads=true&downloadRank=true&stars=true). This project
521 uses [JavaScript Standard Style](https://github.com/feross/standard) - if the name or style choices bother you,
522 you're gonna have to get over it :) If `standard` is good enough for `npm`, it's good enough for `fs-extra`.
524 [![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
527 - First, take a look at existing issues. Those are probably going to be where the priority lies.
528 - More tests for edge cases. Specifically on different platforms. There can never be enough tests.
529 - Improve test coverage. See coveralls output for more info.
530 - After the directory walker is integrated, any function that needs to traverse directories like
531 `copy`, `remove`, or `mkdirs` should be built on top of it.
533 Note: If you make any big changes, **you should definitely file an issue for discussion first.**
535 ### Running the Test Suite
537 fs-extra contains hundreds of tests.
539 - `npm run lint`: runs the linter ([standard](http://standardjs.com/))
540 - `npm run unit`: runs the unit tests
541 - `npm test`: runs both the linter and the tests
546 If you run the tests on the Windows and receive a lot of symbolic link `EPERM` permission errors, it's
547 because on Windows you need elevated privilege to create symbolic links. You can add this to your Windows's
548 account by following the instructions here: http://superuser.com/questions/104845/permission-to-make-symbolic-links-in-windows-7
549 However, I didn't have much luck doing this.
551 Since I develop on Mac OS X, I use VMWare Fusion for Windows testing. I create a shared folder that I map to a drive on Windows.
552 I open the `Node.js command prompt` and run as `Administrator`. I then map the network drive running the following command:
554 net use z: "\\vmware-host\Shared Folders"
556 I can then navigate to my `fs-extra` directory and run the tests.
562 I put a lot of thought into the naming of these functions. Inspired by @coolaj86's request. So he deserves much of the credit for raising the issue. See discussion(s) here:
564 * https://github.com/jprichardson/node-fs-extra/issues/2
565 * https://github.com/flatiron/utile/issues/11
566 * https://github.com/ryanmcgrath/wrench-js/issues/29
567 * https://github.com/substack/node-mkdirp/issues/17
569 First, I believe that in as many cases as possible, the [Node.js naming schemes](http://nodejs.org/api/fs.html) should be chosen. However, there are problems with the Node.js own naming schemes.
571 For example, `fs.readFile()` and `fs.readdir()`: the **F** is capitalized in *File* and the **d** is not capitalized in *dir*. Perhaps a bit pedantic, but they should still be consistent. Also, Node.js has chosen a lot of POSIX naming schemes, which I believe is great. See: `fs.mkdir()`, `fs.rmdir()`, `fs.chown()`, etc.
573 We have a dilemma though. How do you consistently name methods that perform the following POSIX commands: `cp`, `cp -r`, `mkdir -p`, and `rm -rf`?
575 My perspective: when in doubt, err on the side of simplicity. A directory is just a hierarchical grouping of directories and files. Consider that for a moment. So when you want to copy it or remove it, in most cases you'll want to copy or remove all of its contents. When you want to create a directory, if the directory that it's suppose to be contained in does not exist, then in most cases you'll want to create that too.
577 So, if you want to remove a file or a directory regardless of whether it has contents, just call `fs.remove(path)`. If you want to copy a file or a directory whether it has contents, just call `fs.copy(source, destination)`. If you want to create a directory regardless of whether its parent directories exist, just call `fs.mkdirs(path)` or `fs.mkdirp(path)`.
583 `fs-extra` wouldn't be possible without using the modules from the following authors:
585 - [Isaac Shlueter](https://github.com/isaacs)
586 - [Charlie McConnel](https://github.com/avianflu)
587 - [James Halliday](https://github.com/substack)
588 - [Andrew Kelley](https://github.com/andrewrk)
598 Copyright (c) 2011-2016 [JP Richardson](https://github.com/jprichardson)
600 [1]: http://nodejs.org/docs/latest/api/fs.html
603 [jsonfile]: https://github.com/jprichardson/node-jsonfile