1
/* create by AlexZ33 */
// fs 模块

var fs = require('fs');

/*
* fs.open(path, flag, [mode], callback)
* path : 要打开的文件路径
* flags: 打开文件的方式 读/写
* mode: 设置文件的模式 读/写/执行 4/2/1 0777
* callback : 回调
*     err: 文件打开失败的错误保存在err里,如果成功 err为null
*     fd :  被打开文件的标识
 */

fs.open('1.txt','r', function(err, fd) {
     console.log(err);
     console.log(fd);
})

图片描述

fs.realpathSync

// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebookincubator/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);

https://github.com/1397467062...

fs.readdirSync

fs.statSync

clipboard.png

https://github.com/JXtreehous...

clipboard.png

clipboard.png

fs.readFileSync

fs.stat & fs.statSync

1.异步版:fs.stat(path,callback):
    path是一个表示路径的字符串,callback接收两个参数(err,stats),其中stats就是fs.stats的一个实例;
  
2.同步版:fs.statSync(path)
   只接收一个path变量,fs.statSync(path)其实是一个fs.stats的一个实例;

3.再来看fs.stats有以下方法:
    stats.isFile()
    stats.isDirectory()
    stats.isBlockDevice()
    stats.isCharacterDevice()
    stats.isSymbolicLink() (only valid with fs.lstat())
    stats.isFIFO()
    stats.isSocket()

fs.accessSync

常用utils

const createFolder = function (folder) {
  try {
    fs.accessSync(folder);
  } catch (e) {
    fs.mkdirSync(folder);
  }
};

判断目录是否存在

 // ignore not exists dir
  const exists = await fs.exists(logdir)
  if(!exists) return 

删除过期文件

https://github.com/eggjs/egg-...

// https://github.com/eggjs/egg-logrotator/blob/master/app/schedule/clean_log.js
// remove expired log files: xxx.log.YYYY-MM-DD
async function removeExpiredLogFile(logdir, maxDays, logger) {
  // ignore not exists dir
  const exists = await fs.exists(logdir)
  if (!exists) return

  const files = await fs.readdir(logdir)
  const expiredDate = moment().subtract(maxDays, 'days').startOf('date');
  const names = files.filter(file => {
    const name = path.extname(file).substring(1) // 扩展名去掉第一个点.
    if (!/^\d{4}\-\d{2}\-d{2}/.test(name)) {
      return false
    }
    const date = moment(name, 'YYYY-MM-DD').startOf('date')

    if (!date.isValid()) {
      return false
    }

    return date.isBefore(expiredDate)
  })

  if (names.lengh === 0) {
    return;
  }

  console.log(`start remove ${logdir} files: ${names.join(', ')}`)

  await Promise.all(names.map(name => {
    const logfile = path.join(logdir, name)
    return fs.unlink(logfile)
      .catch(err => {
        err.message = ` remove logfile ${logfile} error, ${err.message}`;
        throw new Error(err)
      })
  }))


````
## 遍历目录下的文件目录
reference : https://github.com/chenshenhai/koa2-note/blob/master/demo/mysql/util/walk-file.js

const fs = require('fs')

/**

  • 遍历目录下的文件目录
  • @param {string} pathResolve 需进行遍历的目录路径
  • @param {string} mime 遍历文件的后缀名
  • @return {object} 返回遍历后的目录结果
    */

const getFile = function (pathResolve, mime) {
let files = fs.readdirSync(pathResolve)

let fileList = {}

for (let [i, item] of files.entries()) {

let itemArr = item.split('\.')

let itemMime = (itemArr.length > 1) ? itemArr[itemArr.length - 1] : 'undefined'

let keyName = item + ''
if (mime === itemMime) {
  fileList[item] = pathResolve + item
}

}

return fileList
}

## windows下的路径问题


![clipboard.png](/img/bVbxQri)

// useage

const fs = require('fs')
const getFile = require('./fs.js')

function getSqlMap() {
let basePath = __dirname
basePath = basePath.replace(/\/g, '/')

let pathArr = basePath.split('/')

pathArr = pathArr.splice(0, pathArr.length - 1)
basePath = pathArr.join('/') + '/sql/'
// D:/personal/data-manager/app/dao/sql/

let fileList = getFile(basePath, 'sql')

return fileList
}
console.log(getSqlMap())


![clipboard.png](/img/bVbxQwn)
## 递归读取
https://github.com/fs-utils/fs-readdir-recursive

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

module.exports = read

function read(root, filter, files, prefix) {
prefix = prefix || ''
files = files || []
filter = filter || noDotFiles

var dir = path.join(root, prefix)
// 废弃了 exits
if (!fs.existsSync(dir)) return files
//
if (fs.statSync(dir).isDirectory())

fs.readdirSync(dir)
.filter(function (name, index) {
  return filter(name, index, dir)
})
.forEach(function (name) {
  read(root, filter, files, path.join(prefix, name))
})

else

files.push(prefix)

return files
}

function noDotFiles(x) {
return x[0] !== '.'
}

## 读取文件树 并判断是否 存在给出的路径

https://github.com/vuejs/vue-next/blob/master/scripts/utils.js

`````
const fs = require('fs')

const targets = (exports.targets = fs.readdirSync('packages').filter(f => {
  if (!fs.statSync(`packages/${f}`).isDirectory()) {
    return false
  }
  const pkg = require(`../packages/${f}/package.json`)
  if (pkg.private && !pkg.buildOptions) {
    return false
  }
  return true
}))

exports.fuzzyMatchTarget = (partialTargets, includeAllMatching) => {
  const matched = []
  partialTargets.some(partialTarget => {
    for (const target of targets) {
      if (target.match(partialTarget)) {
        matched.push(target)
        if (!includeAllMatching) {
          break
        }
      }
    }
  })
  if (matched.length) {
    return matched
  } else {
    throw new Error(`Target ${partialTargets} not found!`)
  }
}


````

# 写操作

````

/*!
 * write <https://github.com/jonschlinkert/write>
 *
 * Copyright (c) 2014-2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

var fs = require('fs');
var path = require('path');
var mkdir = require('mkdirp');

/**
 * Asynchronously write a file to disk. Creates any intermediate
 * directories if they don't already exist.
 *
 * ```js
 * var writeFile = require('write');
 * writeFile('foo.txt', 'This is content to write.', function(err) {
 *   if (err) console.log(err);
 * });
 * ```
 *
 * @name  writeFile
 * @param  {String} `dest` Destination file path
 * @param  {String} `str` String to write to disk.
 * @param  {Function} `callback`
 * @api public
 */

module.exports = function writeFile(dest, str, cb) {
  var dir = path.dirname(dest);
  fs.exists(dir, function (exists) {
    if (exists) {
      fs.writeFile(dest, str, cb);
    } else {
      mkdir(dir, function (err) {
        if (err) {
          return cb(err);
        } else {
          fs.writeFile(dest, str, cb);
        }
      });
    }
  });
};

/**
 * Synchronously write files to disk. Creates any intermediate
 * directories if they don't already exist.
 *
 * ```js
 * var writeFile = require('write');
 * writeFile.sync('foo.txt', 'This is content to write.');
 * ```
 *
 * @name  writeFile.sync
 * @param  {String} `dest` Destination file path
 * @param  {String} `str` String to write to disk.
 * @api public
 */

module.exports.sync = function writeFileSync(dest, str) {
  var dir = path.dirname(dest);
  if (!fs.existsSync(dir)) {
    mkdir.sync(dir);
  }
  fs.writeFileSync(dest, str);
};

/**
 * Uses `fs.createWriteStream`, but also creates any intermediate
 * directories if they don't already exist.
 *
 * ```js
 * var write = require('write');
 * write.stream('foo.txt');
 * ```
 *
 * @name  writeFile.stream
 * @param  {String} `dest` Destination file path
 * @return  {Stream} Returns a write stream.
 * @api public
 */

module.exports.stream = function writeFileStream(dest) {
  var dir = path.dirname(dest);
  if (!fs.existsSync(dir)) {
    mkdir.sync(dir);
  }
  return fs.createWriteStream(dest);
};

````

# 删除

使用webpack build文件项目时每次都会生成一个dist目录,有时需要把dist目录里的所以旧文件全部删掉,

除了可以使用rm -rf /dist/命令删除外,还可以使用rimraf /dist/命令

`rimraf`的作用:以包的形式包装`rm -rf`命令,用来删除文件和文件夹的,不管文件夹是否为空,都可删除

局部安装:npm install rimraf --save-dev

全局安装:npm install rimraf -g

使用:rimraf <path> \[<path> ...\]

api:rimraf(f, \[opts\], callback)


也可以用封装好的包 

- del 

https://github.com/sindresorhus/del/blob/master/index.js

# 遍历文件
https://github.com/ks3sdk/ks3-nodejs-sdk/blob/master/lib/util.js

/**

  • 遍历文件
    */

function walkFile(p, opt, fileList) {

var fileList = fileList || [];
var _config = {
    isDeep: false,
    ignore: /\s/ig
};
var dirList = fs.readdirSync(p);
for (var it in opt) {
    _config[it] = opt[it];
}
dirList.forEach(function(item) {
    if (!_config.ignore.test(item)) {
        if (_config.isDeep) {
            if (fs.statSync(p + '/' + item).isDirectory()) {
                fileList.push(p + '/' + item);
                walkFile(p + '/' + item, opt, fileList);
            } else {
                fileList.push(p + '/' + item);
            }
        } else {
            fileList.push(p + '/' + item);
        }
    }

});

return fileList;

}


# 遍历文件夹

https://github.com/ks3sdk/ks3-nodejs-sdk/blob/master/lib/util.js

/**

  • 遍历文件夹
    */

function walkDir(p, opt) {

var fileList = walkFile(p, opt);
var dirList = [];
fileList.forEach(function(item) {
    if (fs.statSync(item).isDirectory()) {
        dirList.push(item);
    }
});

return dirList;

}

# 给文件夹下文件md5加密

/*

  • 为导出的文件生成md5

*/

var fs = require('fs');
var crypto = require('crypto');
var rootPath = '../output/myapp/';
var md5File = 'md5conf.json';
var trimStr = 'myapp';
var removeReg = new RegExp('/' + trimStr + '/', 'g');

var files = fs.readdirSync(rootPath);
var md5Info = {};
// 替换path
files.forEach(function (elem, i) {
var filePath = rootPath + elem;
var stat = fs.statSync(filePath);
if (stat.isFile()) {

var data = fs.readFileSync(filePath, 'utf8');
if(/^.*\.(css|js|html)/.test(elem)) {
  console.log('replace', elem);
  var newData = data.replace(removeReg, '');
  fs.writeFileSync(filePath, newData, 'utf8');
}

}
});
// 计算md5
function calcMd5(path, files) {
files.forEach(function (elem, i) {

var filePath = path + elem;
var stat = fs.statSync(filePath);
if(stat.isDirectory()) {
  calcMd5(filePath + '/', fs.readdirSync(filePath));
} else {
  var data = fs.readFileSync(filePath);
  md5Info[filePath.replace(rootPath, '')] = crypto.createHash('md5').update(data).digest('hex');
}

});
}
calcMd5(rootPath, files);
fs.writeFile(rootPath + md5File, JSON.stringify(md5Info));

# 常见的读写utils
https://github.com/fex-team/fis3/blob/master/lib/util.js

[https://github.com/yantze/fs-lockfile](https://github.com/yantze/fs-lockfile)

# 扩展包
- [fs-extra](https://github.com/jprichardson/node-fs-extra)

使用示例:
https://github.com/1397467062/h5-react/blob/master/H5-react/multipage/scripts/build.js

# 参考
https://www.jianshu.com/p/5683c8a93511
[node命令行工具之实现项目工程自动初始化的标准流程](https://juejin.im/post/5d505356e51d456209238818?utm_source=gold_browser_extension)

白鲸鱼
1k 声望110 粉丝

方寸湛蓝