一、需求

最近整理磁盘,想将散落在磁盘文件夹中所有的 doc、excel、ppt 转移到移动硬盘的某个文件夹中,防止丢失。

为了方便,直接用 nodejs 写了个脚本,感觉还能用,挺方便,不需要手动去操作。

二、运行

有 node 环境可以直接运行。

因为是自己用,就直接把路径和要求写死在了代码中,修改参数的时候,直接修改代码就行了,就不需要在命令行输入参数。

后面加入了命令行参数去使用。

如果使用命令行给参数,则使用方式为:

node ./copyfilefromdir.js srcDir DstDir ext

命令行参数解释:

  • srcDir:需要扫描遍历的文件夹目录
  • DstDir:最终文件复制到的文件夹目录
  • ext:需要匹配的后缀 通过 / 分割多个后缀名

比如:

node .\copyfilefromdir.js H:\websiteimg\网站素材\metro\metro_Design E:\tmpcopy jpg/png/bmp

三、脚本内容

脚本主要包含下面几部分内容:

  • fs/path 模块引入
  • PARAM_STATIC:全局静态变量对象
  • travel(dir, callback):基于递归的文件遍历
  • travelCallback(p):文件遍历回调方法
  • checkFileExtName(src, ext):文件后缀检测
  • copyFileByStream(from, to):文件的流读写操作
  • checkDstDir:检查目标存储文件夹是否存在,不存在则新建
  • main:入口函数 自执行

1. PARAM_STATIC

/**
 * @name PARAM_STATIC
 * @description 不从命令行中获取参数 直接写死 修改静态对象即可
 */
const PARAM_STATIC = {
  srcDir:'H:/websiteimg/网站素材/metro/metro_Design',              // 扫描的文件夹
  dstDir:'E:/tmpcopy',  // 最终文件拷贝的文件夹
  ext:'jpg/png/jpeg'        // 需要的文件后缀
};

2. checkDstDir()

/**
* @name checkDstDir
* @description 判断目标文件夹是否存在 如果不存在则新建目标文件夹
* @param {String} dir 
*/
function checkDstDir(dir){
 if(!fs.existsSync(path.resolve(dir))){
   fs.mkdirSync(path.resolve(dir));
 }
}

3. checkFileExtName()

/**
* @name checkFileExtName
* @description 判断文件后缀名是否符合要求
* @param {String} src 
* @param {String} ext ext 是通过 / 进行分割的字符串 通过正则匹配
*/
function checkFileExtName(src,ext){
 const extName = path.extname(path.resolve(src)).substr(1);
 return ext.includes(extName);
}

4. copyFileByStream()

/**
* @name copyFileByStream
* @description 使用流传输 copy 文件
* @param {String} from 
* @param {String} to 
*/
function copyFileByStream(from,to){
 fs.createReadStream(path.resolve(from)).pipe(fs.createWriteStream(path.resolve(to)));
}

5. travelCallback()

/**
 * @name travelCallback
 * @description 遍历文件的回调方法 在回调方法中调用文件类型判断及文件类型读写操作
 * @param {String} p 文件路径
 */
function travelCallback(p){
 if(checkFileExtName(p,PARAM_STATIC.ext)){
   copyFileByStream(p,path.join(PARAM_STATIC.dstDir,p.toString().replace(/\\/g,'-').replace(/:/g,'')));
   console.log('[Done]:'+p);
 }
}

6. travel()

/**
* @name travel
* @description 遍历文件夹操作
* @param {String} dir 
* @param {function} callback 
*/
function travel(dir,callback){
 dir = path.resolve(dir);
 fs.stat(dir,(err,stats)=>{
   if(err) return console.error('Error:',err);
   if(!stats.isDirectory()){
     callback(dir);
     return ;
   }
   fs.readdir(dir,(err,files)=>{
     if(err) return console.error('Error:',err);
     files.forEach((file)=>{
       travel(path.join(dir,file),callback);
     });
   });
 });
}

7. main()

/**
* @name main
* @description 主函数
*/
function main(){
  // 命令行参数初始化工作
 const argvs = process.argv.slice(2);
 PARAM_STATIC.srcDir = argvs[0] ? argvs[0] : PARAM_STATIC.srcDir;
 PARAM_STATIC.dstDir = argvs[1] ? argvs[1] : PARAM_STATIC.dstDir;
 PARAM_STATIC.ext = argvs[3] ? argvs[3] : PARAM_STATIC.ext;
 checkDstDir(PARAM_STATIC.dstDir);
 travel(PARAM_STATIC.srcDir,travelCallback);
}

四、完整代码

我在 gitosc 上放了一份完整的代码片段:

五、效果

我在copy图片的时候,速度还是挺快的。

1.jpg

2.jpg