node-"fs-extra"模块代替fs使用

2018-07-21 · xiejiahe

code

fs-extra是fs的一个扩展,提供了非常多的便利API,并且继承了fs所有方法和为fs方法添加了promise的支持。

它应该是 fs 的替代品。

为什么?

我厌倦了包括mkdirp,rimraf以及ncp在我的大部分项目中。

解决了什么问题

使用前,必须了解第三方库给现有库解决了哪些问题,不要为了使用而使用。

fs-extra模拟了类似如Linux下的命令:

root$ rm -rf /
root$ mv tmpDir tmpNewDir
root$ mkdir -p one/two
root$ cp -r tmp tmpNew
...

这很方便不是吗?这才让我深深地爱上了它!

嘻嘻

安装

npm install fs-extra -S

用法

应该总是fs-extra代替fs使用,所有fs方法都附在fs-extra,fs如果未传递回调,则所有方法都将返回promise。

不再需要这个

const fs = require('fs');

你现在可以这样做

const fs = require('fs-extra');

如果你希望明确表示你在使用fs-extra,可以将fs标识符改为fse

const fse = require('fs-extra');

你可以保留两者使用,但它是多余的,因为 fs-extra 继承了fs

const fs = require('fs');
const fse = require('fs-extra');

Sync vs Async vs Async/Await

大多数方法默认为异步,如果未传递回调,则所有异步方法将返回一个promise。

一个典型的例子:

const fs = require('fs-extra')

// 异步方法,返回promise
fs.copy('/tmp/myfile', '/tmp/mynewfile')
  .then(() => console.log('success!'))
  .catch(err => console.error(err))

// 异步方法,回调函数
fs.copy('/tmp/myfile', '/tmp/mynewfile', err => {
  if (err) return console.error(err)
  console.log('success!')
})

// 同步方法,注意必须使用try catch包裹着才能捕获错误
try {
  fs.copySync('/tmp/myfile', '/tmp/mynewfile')
  console.log('success!')
} catch (err) {
  console.error(err)
}

// Async/Await:
async function copyFiles () {
  try {
    await fs.copy('/tmp/myfile', '/tmp/mynewfile')
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

copyFiles()

API Methods

下面的所有方法都是fs-extra扩展方法

Async/异步

  • copy
  • emptyDir (别名:emptydir)
  • ensureFile
  • ensureDir (别名:mkdirp、mkdirs)
  • ensureLink
  • ensureSymlink
  • mkdirp
  • mkdirs
  • move
  • outputFile
  • outputJson (别名:outputJSON)
  • pathExists
  • readJson (别名:readJSON)
  • remove
  • writeJson (别名:writeJSON)

Sync/同步

  • copySync
  • emptyDirSync
  • ensureFileSync
  • ensureDirSync
  • ensureLinkSync
  • ensureSymlinkSync
  • mkdirpSync
  • mkdirsSync
  • moveSync
  • outputFileSync
  • outputJsonSync
  • pathExistsSync
  • readJsonSync
  • removeSync
  • writeJsonSync

1、copy(src: string, dest: string, [options: object, callback: func])

复制文件或目录,目录可以包含内容,类似 cp -r

  • src 请注意,如果src是目录,它将复制此目录内的所有内容,而不是整个目录本身
  • dest 请注意,如果src是文件,dest则不能是目录
  • options
    • overwrite : 覆盖现有文件或目录,默认为true。请注意,如果将此设置为false并且目标存在,则复制操作将无提示失败。使用该errorOnExist选项可更改此行为。
    • errorOnExist : 当overwrite为false和目标存在时,抛出错误。默认是false。
    • dereference : dereference symlinks,默认是false。
    • preserveTimestamps : 如果为true,将设置对原始源文件的最后修改和访问时间。如果为false,则时间戳行为取决于操作系统。默认是false。
    • filter : 过滤复制文件的功能。返回true包含,false排除。也可以返回Promise解析为true或false(或传入async函数)。
  • callback 回调函数

例子:

const fs = require('fs-extra')

// With a callback:
fs.copy('/tmp/myfile', '/tmp/mynewfile', err => {
  if (err) return console.error(err)

  console.log('success!')
}) // copies file

fs.copy('/tmp/mydir', '/tmp/mynewdir', err => {
  if (err) return console.error(err)

  console.log('success!')
}) // copies directory, even if it has subdirectories or files

// With Promises:
fs.copy('/tmp/myfile', '/tmp/mynewfile')
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example () {
  try {
    await fs.copy('/tmp/myfile', '/tmp/mynewfile')
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

example()

使用过滤函数

const fs = require('fs-extra')

const filterFunc = (src, dest) => {
  // your logic here
  // it will be copied if return true
}

fs.copy('/tmp/mydir', '/tmp/mynewdir', { filter: filterFunc }, err => {
  if (err) return console.error(err)

  console.log('success!')
})

2、emptyDir(dir: string, [callback: function])

确保目录为空。如果目录不为空,则删除目录内容。如果该目录不存在,则创建该目录。目录本身不会被删除。

别名: emptydir()

  • dir 目标路径
  • callback 回调方法

例子:

const fs = require('fs-extra')

// assume this directory has a lot of files and folders
// With a callback:
fs.emptyDir('/tmp/some/dir', err => {
  if (err) return console.error(err)

  console.log('success!')
})

// With Promises:
fs.emptyDir('/tmp/some/dir')
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example () {
  try {
    await fs.emptyDir('/tmp/some/dir')
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

example()

3、ensureFile(file: string, [callback: func])

确保文件存在。如果请求创建的文件位于不存在的目录中,则会创建这些目录。如果该文件已存在,则不进行修改。

别名: createFile()

  • file 目标路径
  • callback 回调方法

例子:

const fs = require('fs-extra')

const file = '/tmp/this/path/does/not/exist/file.txt'

// With a callback:
fs.ensureFile(file, err => {
  console.log(err) // => null
  // file has now been created, including the directory it is to be placed in
})

// With Promises:
fs.ensureFile(file)
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example (f) {
  try {
    await fs.ensureFile(f)
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

example(file)

4、ensureDir(dir: string, [callback: func])

如果目录结构不存在,则创建它,如果目录存在,则不进行创建,类似mkdir -p。

别名: mkdirs(), mkdirp()

  • dir 目标路径
  • callback 回调方法

例子:

const fs = require('fs-extra')

const dir = '/tmp/this/path/does/not/exist'

// With a callback:
fs.ensureDir(dir, err => {
  console.log(err) // => null
  // dir has now been created, including the directory it is to be placed in
})

// With Promises:
fs.ensureDir(dir)
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example (directory) {
  try {
    await fs.ensureDir(directory)
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

example(dir)

5、ensureLink(srcpath: string, dstpath: string, [callback: func])

确保链接存在。如果目录结构不存在,则创建它。

  • srcpath 源路径
  • dstpath 目标路径
  • callback 回调方法

例子

const fs = require('fs-extra')

const srcpath = '/tmp/file.txt'
const dstpath = '/tmp/this/path/does/not/exist/file.txt'

// With a callback:
fs.ensureLink(srcpath, dstpath, err => {
  console.log(err) // => null
  // link has now been created, including the directory it is to be placed in
})

// With Promises:
fs.ensureLink(srcpath, dstpath)
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example (src, dest) {
  try {
    await fs.ensureLink(src, dest)
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

example(srcpath, dstpath)

6、ensureSymlink(srcpath: string, dstpath: string, [callback: func])

确保符号链接存在。如果目录结构不存在,则创建它。

  • srcpath 源路径
  • dstpath 目标路径
  • callback 回调方法
const fs = require('fs-extra')

const srcpath = '/tmp/file.txt'
const dstpath = '/tmp/this/path/does/not/exist/file.txt'

// With a callback:
fs.ensureSymlink(srcpath, dstpath, err => {
  console.log(err) // => null
  // symlink has now been created, including the directory it is to be placed in
})

// With Promises:
fs.ensureSymlink(srcpath, dstpath)
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example (src, dest) {
  try {
    await fs.ensureSymlink(src, dest)
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

example(srcpath, dstpath)

7、move(src: string, dest: string, [options: object, callback: func])

移动文件或目录,甚至跨设备。 类似 mv

  • srcpath 源路径
  • dstpath 目标路径
  • options
    • overwrite : 覆盖现有文件或目录,默认为false。
  • callback 回调方法

例子:

const fs = require('fs-extra')

const srcpath = '/tmp/file.txt'
const dstpath = '/tmp/this/path/does/not/exist/file.txt'

// With a callback:
fs.move(srcpath, dstpath, err => {
  if (err) return console.error(err)

  console.log('success!')
})

// With Promises:
fs.move(srcpath, dstpath, {
  overwrite: true
})
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example (src, dest) {
  try {
    await fs.move(srcpath, dstpath)
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

example(srcpath, dstpath)

8、outputFile(file: stirng, data: string|Buffer|Uint8Array, [options: string|object, callback: func])

几乎与writeFile(即它覆盖)相同,除了如果父目录不存在,则创建它。file必须是文件路径(不允许使用缓冲区或文件描述符)。

  • file 写入文件路径
  • data 写入文件的数据
  • options
  • callback 回调方法

例子:

const fs = require('fs-extra')

const file = '/tmp/this/path/does/not/exist/file.txt'

// With a callback:
fs.outputFile(file, 'hello!', err => {
  console.log(err) // => null

  fs.readFile(file, 'utf8', (err, data) => {
    if (err) return console.error(err)
    console.log(data) // => hello!
  })
})

// With Promises:
fs.outputFile(file, 'hello!')
.then(() => fs.readFile(file, 'utf8'))
.then(data => {
  console.log(data) // => hello!
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example (f) {
  try {
    await fs.outputFile(f, 'hello!')

    const data = await fs.readFile(f, 'utf8')

    console.log(data) // => hello!
  } catch (err) {
    console.error(err)
  }
}

example(file)

9、outputJson(file: string, object: object, [options: object, callback: func])

几乎相同writeJson,除了如果目录不存在,它就被创建了。

别名: outputJSON()

  • file 写入文件路径
  • object 写入文件的JSON对象
  • options
    • encoding | 默认为 ‘utf8’
    • mode 默认为 0o666
    • flag 详见支持的文件系统flag, 默认为 ‘w’
    • spaces <number|string> 缩进的空格数; 或者用于缩进的字符串(即传递’\t’标签缩进)
    • EOL 设置EOL字符。默认是\n。
    • replacer JSON replacer
  • callback 回调方法

例子:

const fs = require('fs-extra')

const file = '/tmp/this/path/does/not/exist/file.json'

// With a callback:
fs.outputJson(file, {name: 'JP'}, err => {
  console.log(err) // => null

  fs.readJson(file, (err, data) => {
    if (err) return console.error(err)
    console.log(data.name) // => JP
  })
})

// With Promises:
fs.outputJson(file, {name: 'JP'})
.then(() => fs.readJson(file))
.then(data => {
  console.log(data.name) // => JP
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example (f) {
  try {
    await fs.outputJson(f, {name: 'JP'})

    const data = await fs.readJson(f)

    console.log(data.name) // => JP
  } catch (err) {
    console.error(err)
  }
}

example(file)

10、pathExists(file: string [, callback: func])

通过检查文件系统来测试给定路径是否存在。类似fs.exists

  • file 文件路径
  • callback 回调函数

例子:

const fs = require('fs-extra')

const file = '/tmp/this/path/does/not/exist/file.txt'

// With a callback:
fs.pathExists(file, (err, exists) => {
  console.log(err) // => null
  console.log(exists) // => false
})

// Promise usage:
fs.pathExists(file)
  .then(exists => console.log(exists)) // => false

// With async/await:
async function example (f) {
  const exists = await fs.pathExists(f)

  console.log(exists) // => false
}

example(file)

11、readJson(file: string, [options: object, callback: func])

读取JSON文件,然后将其解析为对象

别名: readJSON()

  • file JSON文件路径
  • options
    • throws 如果为false并且JSON无效,它将不会抛出err, 默认true
  • callback 回调函数

例子:

const fs = require('fs-extra')

// With a callback:
fs.readJson('./package.json', (err, packageObj) => {
  if (err) console.error(err)

  console.log(packageObj.version) // => 0.1.3
})

// With Promises:
fs.readJson('./package.json')
.then(packageObj => {
  console.log(packageObj.version) // => 0.1.3
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example () {
  try {
    const packageObj = await fs.readJson('./package.json')

    console.log(packageObj.version) // => 0.1.3
  } catch (err) {
    console.error(err)
  }
}

example()

12、remove(path: string, [callback: func])

删除文件或目录。该目录可以包含内容, 类似 rm -rf

  • path 目标路径
  • callback 回调函数

例子:

const fs = require('fs-extra')

// remove file
// With a callback:
fs.remove('/tmp/myfile', err => {
  if (err) return console.error(err)

  console.log('success!')
})

fs.remove('/home/jprichardson', err => {
  if (err) return console.error(err)

  console.log('success!') // I just deleted my entire HOME directory.
})

// With Promises:
fs.remove('/tmp/myfile')
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example (src, dest) {
  try {
    await fs.remove('/tmp/myfile')
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

example()

13、writeJson(file, object, [options, callback])

将对象写入JSON文件, 几乎与outputJson相同,除了必须保证目录存在外。

别名: writeJSON()

  • file 写入文件路径
  • object 写入文件的JSON对象
  • options
    • encoding | 默认为 ‘utf8’
    • mode 默认为 0o666
    • flag 详见支持的文件系统flag, 默认为 ‘w’
    • spaces <number|string> 缩进的空格数; 或者用于缩进的字符串(即传递’\t’标签缩进)
    • EOL 设置EOL字符。默认是\n。
    • replacer JSON replacer
  • callback 回调方法

例子:

const fs = require('fs-extra')

// With a callback:
fs.writeJson('./package.json', {name: 'fs-extra'}, err => {
  if (err) return console.error(err)

  console.log('success!')
})

// With Promises:
fs.writeJson('./package.json', {name: 'fs-extra'})
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// With async/await:
async function example () {
  try {
    await fs.writeJson('./package.json', {name: 'fs-extra'})
    console.log('success!')
  } catch (err) {
    console.error(err)
  }
}

example()

写在最后

毋庸置疑fs-extra用在生产环境绝对是不错的选择,但是想要玩转黑科技还是要多多了解fs模块,毕竟它才是老大。

Node.js
原创文章,转载请注明出处。