2012-12-09 92 views
79

是否有一種更簡單的方法來複制文件夾及其所有內容,而無需手動執行fs.readirfs.readfilefs.writefile的遞歸序列?在node.js中遞歸複製文件夾

只是想知道如果我錯過了這會非常喜歡這個

fs.copy("/path/to/source/folder","/path/to/destination/folder"); 
+2

有沒有辦法做到這一點沒有任何模塊?也許遞歸函數/代碼片斷 - 它? – Sukima

+0

@Sukima - 查看我的回答[here](http://stackoverflow.com/a/21321485/552792)。 – jmort253

回答

74

工作的功能,您可以使用ncp模塊。我認爲這是你需要的

+0

完美! 'npm install ncp'並在30秒內工作。謝謝。 – Aebsubis

+1

扳手對我來說更好,因爲它支持更多選項。例如,使用NCP無法解析符號鏈接。 –

+0

作爲一個驚人的獎勵,可以在跨平臺的npm運行腳本中使用ncp。 – Ciantic

36

有一些模塊支持複製文件夾的內容。最流行的是wrench

// Deep-copy an existing directory 
wrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up'); 

另一種方法是node-fs-extra

fs.copy('/tmp/mydir', '/tmp/mynewdir', function (err) { 
    if (err) { 
    console.error(err); 
    } else { 
    console.log("success!"); 
    } 
}); //copies directory, even if it has subdirectories or files 
+2

扳手失敗,如果目錄要複製包含符號鏈接 – DoubleMalt

+2

它也失敗,如果該目錄已經存在,[ncp](https://npmjs.org/package/ncp)在包裏工作。 – blented

+2

node-fs-extra爲我工作。它繼承了原始的fs,我喜歡它是處理過程的方式。在應用程序中更新的代碼較少。 – dvdmn

2

因爲我只是構建一個簡單的腳本節點,我不想腳本的用戶需要導入一堆外部模塊和依賴關係,所以我放了我的思想上限,並搜索了來自bash shell的運行命令。

這Node.js的代碼片段循環地將一個名爲node-webkit.app文件夾到一個文件夾,名爲編譯:

child = exec("cp -r node-webkit.app build", function(error, stdout, stderr) { 
     sys.print("stdout: " + stdout); 
     sys.print("stderr: " + stderr); 
     if(error !== null) { 
      console.log("exec error: " + error); 
     } else { 

     } 
    }); 

感謝Lance Pollard at dzone你爲我開始。

上面的代碼片段僅限於基於Unix的平臺,如Mac OS和Linux,但類似的技術可能適用於Windows。

18
/** 
* Look ma, it's cp -R. 
* @param {string} src The path to the thing to copy. 
* @param {string} dest The path to the new copy. 
*/ 
var copyRecursiveSync = function(src, dest) { 
    var exists = fs.existsSync(src); 
    var stats = exists && fs.statSync(src); 
    var isDirectory = exists && stats.isDirectory(); 
    if (exists && isDirectory) { 
    fs.mkdirSync(dest); 
    fs.readdirSync(src).forEach(function(childItemName) { 
     copyRecursiveSync(path.join(src, childItemName), 
         path.join(dest, childItemName)); 
    }); 
    } else { 
    fs.linkSync(src, dest); 
    } 
}; 
+2

可以優化爲'if(isDirectory) - 'isDirectory'已經檢查'exists'。 – Qix

+4

這個功能不會複製它只是鏈接所有文件! –

+2

即使你插入一個真正的複製函數,你也不應該遵循符號鏈接(使用'fs.lstatSync'而不是'fs.statSync') –

30

這是我的方法來解決這個問題,沒有任何額外的模塊。只需使用內置的fspath模塊。

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

function copyFileSync(source, target) { 

    var targetFile = target; 

    //if target is a directory a new file with the same name will be created 
    if (fs.existsSync(target)) { 
     if (fs.lstatSync(target).isDirectory()) { 
      targetFile = path.join(target, path.basename(source)); 
     } 
    } 

    fs.writeFileSync(targetFile, fs.readFileSync(source)); 
} 

function copyFolderRecursiveSync(source, target) { 
    var files = []; 

    //check if folder needs to be created or integrated 
    var targetFolder = path.join(target, path.basename(source)); 
    if (!fs.existsSync(targetFolder)) { 
     fs.mkdirSync(targetFolder); 
    } 

    //copy 
    if (fs.lstatSync(source).isDirectory()) { 
     files = fs.readdirSync(source); 
     files.forEach(function (file) { 
      var curSource = path.join(source, file); 
      if (fs.lstatSync(curSource).isDirectory()) { 
       copyFolderRecursiveSync(curSource, targetFolder); 
      } else { 
       copyFileSync(curSource, targetFolder); 
      } 
     }); 
    } 
} 
+0

它不會複製文件夾,如果他們的名字中有空格 – 31415926

+0

對我來說,它會複製其名稱中包含空格的文件夾。也許這是由@victor糾正的錯誤引起的。由於我正在很經常地使用這個功能(在當前狀態下,因爲我忘記更新同樣的更正勝利者),所以我確信它一般工作。 –

+0

@SimonZyx,'fs.createReadStream'不同步。將其更改爲'fs.writeFileSync(target,fs.readFileSync(source));'將使它成爲現實。 –

0

此代碼將工作得很好,遞歸地將任何文件夾複製到任何位置。僅限Windows。

var child=require("child_process"); 
function copySync(from,to){ 
    from=from.replace(/\//gim,"\\"); 
    to=to.replace(/\//gim,"\\"); 
    child.exec("xcopy /y /q \""+from+"\\*\" \""+to+"\\\""); 
} 

完美適用於我的基於文本的遊戲來創建新玩家。

8

我創建了一個小型工作的例子,複製源文件夾到另一個目標文件夾中僅有幾步之遙(基於@ shift66答案使用NCP):

步驟1 - 安裝NCP模塊:

npm install ncp --save 

第2步 - 創建副本。JS(修改srcPath和destPath瓦爾任何你需要的):

var path = require('path'); 
var ncp = require('ncp').ncp; 

ncp.limit = 16; 

var srcPath = path.dirname(require.main.filename); //current folder 
var destPath = '/path/to/destination/folder'; //Any destination folder 

console.log('Copying files...'); 
ncp(srcPath, destPath, function (err) { 
    if (err) { 
    return console.error(err); 
    } 
    console.log('Copying files complete.'); 
}); 

第3步 - 運行

node copy.js 
6

對Linux/Unix操作系統,你可以使用shell語法

const shell = require('child_process').execSync ; 

const src= `/path/src`; 
const dist= `/path/dist`; 

shell(`mkdir -p ${dist}`); 
shell(`cp -r ${src}/* ${dist}`); 

就是這樣!

+1

應該是公認的答案 – the0ther

+1

歡迎您 –

+1

這是最簡單的解決方案。無需重新發明UNIX工具! –

2

fs-extra模塊就像一個魅力。

安裝FS-額外

$ npm install fs-extra 

以下是源目錄複製到目標目錄下的程序。

// include fs-extra package 
var fs = require("fs-extra"); 

var source = 'folderA' 
var destination = 'folderB' 

// copy source folder to destination 
fs.copy(source, destination, function (err) { 
    if (err){ 
     console.log('An error occured while copying the folder.') 
     return console.error(err) 
    } 
    console.log('Copy completed!') 
}); 

參考

FS-EXTRA:https://www.npmjs.com/package/fs-extra

例子:Node.js Tutorial - Node.js Copy a Folder

0

YES,ncpcool雖然...

你可能想/應promisify其功能是super cool。既然你在這裏,把它添加到一個tools文件重用。

以下是一個工作版本,它是Async並使用Promises


index.js

const {copyFolder} = require('./tools/'); 

return copyFolder(
    yourSourcePath, 
    yourDestinationPath 
) 
.then(() => { 
    console.log('-> Backup completed.') 
}) .catch((err) => { 
    console.log("-> [ERR] Could not copy the folder: ", err); 
}) 

tools.js

const ncp = require("ncp"); 

/** 
* Promise Version of ncp.ncp() 
* 
* This function promisifies ncp.ncp(). 
* We take the asynchronous function ncp.ncp() with 
* callback semantics and derive from it a new function with 
* promise semantics. 
*/ 
ncp.ncpAsync = function (sourcePath, destinationPath) { 
    return new Promise(function (resolve, reject) { 
     try { 
      ncp.ncp(sourcePath, destinationPath, function(err){ 
       if (err) reject(err); else resolve(); 
      }); 
     } catch (err) { 
      reject(err); 
     } 
    }); 
}; 

/** 
* Utility function to copy folders asynchronously using 
* the Promise returned by ncp.ncp(). 
*/ 
const copyFolder = (sourcePath, destinationPath) => { 
    return ncp.ncpAsync(sourcePath, destinationPath, function (err) { 
     if (err) { 
      return console.error(err); 
     } 
    }); 
} 
module.exports.copyFolder = copyFolder;