思路:

1、callback 驱动

2、递归所有需要复制文件

3、在一定阀值下并发复制文件

4、运行需要安装 async.js     npm install async

代码如下:

  1. var async = require("async");
  2. var fs = require("fs");
  3. var path = require("path");
  4. // cursively make dir
  5. function mkdirs(p, mode, f, made) {
  6. if (typeof mode === 'function' || mode === undefined) {
  7. f = mode;
  8. mode = 0777 & (~process.umask());
  9. }
  10. if (!made)
  11. made = null;
  12. var cb = f || function () {};
  13. if (typeof mode === 'string')
  14. mode = parseInt(mode, 8);
  15. p = path.resolve(p);
  16. fs.mkdir(p, mode, function (er) {
  17. if (!er) {
  18. made = made || p;
  19. return cb(null, made);
  20. }
  21. switch (er.code) {
  22. case 'ENOENT':
  23. mkdirs(path.dirname(p), mode, function (er, made) {
  24. if (er) {
  25. cb(er, made);
  26. } else {
  27. mkdirs(p, mode, cb, made);
  28. }
  29. });
  30. break;
  31. // In the case of any other error, just see if there's a dir
  32. // there already.  If so, then hooray!  If not, then something
  33. // is borked.
  34. default:
  35. fs.stat(p, function (er2, stat) {
  36. // if the stat fails, then that's super weird.
  37. // let the original error be the failure reason.
  38. if (er2 || !stat.isDirectory()) {
  39. cb(er, made);
  40. } else {
  41. cb(null, made)
  42. };
  43. });
  44. break;
  45. }
  46. });
  47. }
  48. // single file copy
  49. function copyFile(file, toDir, cb) {
  50. async.waterfall([
  51. function (callback) {
  52. fs.exists(toDir, function (exists) {
  53. if (exists) {
  54. callback(null, false);
  55. } else {
  56. callback(null, true);
  57. }
  58. });
  59. }, function (need, callback) {
  60. if (need) {
  61. mkdirs(path.dirname(toDir), callback);
  62. } else {
  63. callback(null, true);
  64. }
  65. }, function (p, callback) {
  66. var reads = fs.createReadStream(file);
  67. var writes = fs.createWriteStream(path.join(path.dirname(toDir), path.basename(file)));
  68. reads.pipe(writes);
  69. //don't forget close the  when  all the data are read
  70. reads.on("end", function () {
  71. writes.end();
  72. callback(null);
  73. });
  74. reads.on("error", function (err) {
  75. console.log("error occur in reads");
  76. callback(true, err);
  77. });
  78. }
  79. ], cb);
  80. }
  81. // cursively count the  files that need to be copied
  82. function _ccoutTask(from, to, cbw) {
  83. async.waterfall([
  84. function (callback) {
  85. fs.stat(from, callback);
  86. },
  87. function (stats, callback) {
  88. if (stats.isFile()) {
  89. cbw.addFile(from, to);
  90. callback(null, []);
  91. } else if (stats.isDirectory()) {
  92. fs.readdir(from, callback);
  93. }
  94. },
  95. function (files, callback) {
  96. if (files.length) {
  97. for (var i = 0; i < files.length; i++) {
  98. _ccoutTask(path.join(from, files[i]), path.join(to, files[i]), cbw.increase());
  99. }
  100. }
  101. callback(null);
  102. }
  103. ], cbw);
  104. }
  105. // wrap the callback before counting
  106. function ccoutTask(from, to, cb) {
  107. var files = [];
  108. var count = 1;
  109. function wrapper(err) {
  110. count--;
  111. if (err || count <= 0) {
  112. cb(err, files)
  113. }
  114. }
  115. wrapper.increase = function () {
  116. count++;
  117. return wrapper;
  118. }
  119. wrapper.addFile = function (file, dir) {
  120. files.push({
  121. file : file,
  122. dir : dir
  123. });
  124. }
  125. _ccoutTask(from, to, wrapper);
  126. }
  127. function copyDir(from, to, cb) {
  128. if(!cb){
  129. cb=function(){};
  130. }
  131. async.waterfall([
  132. function (callback) {
  133. fs.exists(from, function (exists) {
  134. if (exists) {
  135. callback(null, true);
  136. } else {
  137. console.log(from + " not exists");
  138. callback(true);
  139. }
  140. });
  141. },
  142. function (exists, callback) {
  143. fs.stat(from, callback);
  144. },
  145. function (stats, callback) {
  146. if (stats.isFile()) {
  147. // one file copy
  148. copyFile(from, to, function (err) {
  149. if (err) {
  150. // break the waterfall
  151. callback(true);
  152. } else {
  153. callback(null, []);
  154. }
  155. });
  156. } else if (stats.isDirectory()) {
  157. ccoutTask(from, to, callback);
  158. }
  159. },
  160. function (files, callback) {
  161. // prevent reaching to max file open limit
  162. async.mapLimit(files, 10, function (f, cb) {
  163. copyFile(f.file, f.dir, cb);
  164. }, callback);
  165. }
  166. ], cb);
  167. }
  168. var start = new Date().getTime();
  169. copyDir("F:\\gear", "F:\\gear2", function (err) {
  170. if (err) {
  171. console.log("error ocur");
  172. console.dir(err);
  173. } else {
  174. console.log("copy ok");
  175. console.log("consume time:" + (new Date().getTime() - start))
  176. }
  177. });

纯异步nodejs文件夹(目录)复制的更多相关文章

  1. 工具:从一个文件夹中复制jar到另一个文件夹中

    工具类:从一个文件夹中复制jar到另一个文件夹中 需要的小伙伴可以试一试,很爽哦,有时候真的很需要! 需求:当我们拿到一个maven项目时,而maven项目的jar包都是通过pom.xml文件管理的, ...

  2. 【转载】ASP.NET工具类:文件夹目录Directory操作工具类

    在ASP.NET开发网站的过程中,有时候会涉及到文件夹相关操作,如判断文件夹目录是否存在.删除文件夹目录.创建文件.删除文件.复制文件夹等等.这一批有关文件目录的操作可以通过Directory类.Fi ...

  3. A1制作文件夹目录

    第一步 在文件夹目录下建立bat文件,填写以下内容: dir *.* /B >目录.txt 最后双击bat文件. 第二步 运行后复制目录.txt文件内容到空白excel 使用hyperlink函 ...

  4. Node.js 文件夹目录结构创建

    第一次接触NodeJS的文件系统就被它的异步的响应给搞晕了,后来发现NodeJS判断文件夹是否存在和创建文件夹是还有同步方法的,但是还是想尝试使用异步的方法去实现. 使用的方法:fs.exists(p ...

  5. Java修炼——文件夹的复制

    文件夹的复制用到了俩个流:缓冲流和文件字节流 缓冲流用来加快写入和读取速度. 在这里我简述一下复制文件夹的过程,当然复制文件夹都可以,复制文件更是不在话下 1.首先要明确俩点.要复制的文件夹的位置(源 ...

  6. linux系统下修改文件夹目录权限

    linux系统下修改文件夹目录权限 文件夹权限问题 Linux.Fedora.Ubuntu修改文件.文件夹权限的方法差不多.很多人开始接触Linux时都很头痛Linux的文件权限问题.这里告诉大家如何 ...

  7. linux下跨服务器文件文件夹的复制

    文件的复制:scp –P (端口号) ./authorized_keys berchina@hadoop002:/home/berchina 文件夹的复制:scp -r -P (端口号) /home/ ...

  8. 【转载】C#递归删除文件夹目录及文件

    在C#文件操作过程中,有时候需要删除相应目录,如果文件夹中含有其他文件夹或者文件,也需要一并进行删除,此时可能就需要使用递归来删除文件夹目录以及文件,递归过程中,如果遍历的对象是文件夹,则删除文件夹, ...

  9. C# -- 使用递归列出文件夹目录及目录下的文件

    使用递归列出文件夹目录及目录的下文件 1.使用递归列出文件夹目录及目录下文件,并将文件目录结构在TreeView控件中显示出来. 新建一个WinForm应用程序,放置一个TreeView控件: 代码实 ...

随机推荐

  1. ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 路由 前两章节中,我们提到 ASP.NET Core 支持 MVC 开发 ...

  2. theano 深度学习大全

    1. theano 的设计理念与性能分析 Theano: a CPU and GPU Math Expression Compiler 2. thenao 深度学习 Deep Learning Tut ...

  3. WinForm和WPF颜色对象的转换

    原文:WinForm和WPF颜色对象的转换 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/huangli321456/article/details ...

  4. SyncML协议简述(和HTTP协议有点类似)

    目前,移动计算和通信设备的流行很大部分原因是因为它们具有一些方便的功能,比如说在需要时可以发送信息给其他用户,用户希望随时随地都可以利用掌上设备访问信息和执行应用程序,甚至在飞行中也可以获得和更新信息 ...

  5. iPhone开发笔记(20)EGOImageView的使用方法及注意事项

    EGOImageView是一种实现网络图片的异步加载和缓存的第三方类库,具有相同功能的第三方类库还有SDWebImage.但是相比两个类库的安装和使用来说,EGOImageView更简单一些,下面就介 ...

  6. WPF控件TextBlock中文字自动换行

    原文:WPF控件TextBlock中文字自动换行 在很多的WPF项目中,往往为了追求界面的美观,需要控制控件中文字的换行显示,现对TextBlock控件换行的实现方式进行总结,希望大家多多拍砖!!! ...

  7. SAP和去哪儿网面试感悟

    这两天先后面了两家公司,个人感觉挺有意思,就写下来.现在是4月份,校招基本没有了,去哪儿网刚好有春招,我就去试试.SAP是同学推荐的. 去哪儿.参加笔试,个人感觉还行.半个月后收到面试通知.到了面试现 ...

  8. QuickReport根据每行的内容长度动态调整DetailBand1的行高

    procedure TPosPubFactureRep.DetailBand1BeforePrint(Sender: TQRCustomBand; var PrintBand: Boolean); v ...

  9. 无法删除 NTFS 盘上的文件或文件夹(对Windows文件的各种情况有比较详细的描述)

    简介 本文介绍您可能无法删除 NTFS 文件系统卷上的文件或文件夹的原因,以及如何分析造成此问题的不同原因从而解决此问题. 更多信息 注意:在内部,NTFS 将文件夹作为特殊类型的文件进行处理.因此, ...

  10. JVM的几个介绍

    关于jvm内存的几点 jvm在运行时分为方法区(Method Area) .虚拟机栈(VM Stack).本地方法栈(Native Method Stack).堆 (Heap).程序计数器 (Prog ...