是否有一种更简单的方法来复制文件夹及其所有内容,而无需手动执行一系列的fs。readir, fs。readfile, fs。writefile递归?
我只是想知道我是否错过了一个函数,理想情况下是这样工作的:
fs.copy("/path/to/source/folder", "/path/to/destination/folder");
关于这个历史问题。注意fs。Cp和fs。cpSync可以递归复制文件夹,在Node v16+中可用
是否有一种更简单的方法来复制文件夹及其所有内容,而无需手动执行一系列的fs。readir, fs。readfile, fs。writefile递归?
我只是想知道我是否错过了一个函数,理想情况下是这样工作的:
fs.copy("/path/to/source/folder", "/path/to/destination/folder");
关于这个历史问题。注意fs。Cp和fs。cpSync可以递归复制文件夹,在Node v16+中可用
当前回答
对于没有fs的旧节点版本。cp,我在紧要关头使用这个来避免需要第三方库:
const fs = require("fs").promises;
const path = require("path");
const cp = async (src, dest) => {
const lstat = await fs.lstat(src).catch(err => false);
if (!lstat) {
return;
}
else if (await lstat.isFile()) {
await fs.copyFile(src, dest);
}
else if (await lstat.isDirectory()) {
await fs.mkdir(dest).catch(err => {});
for (const f of await fs.readdir(src)) {
await cp(path.join(src, f), path.join(dest, f));
}
}
};
// sample usage
(async () => {
const src = "foo";
const dst = "bar";
for (const f of await fs.readdir(src)) {
await cp(path.join(src, f), path.join(dst, f));
}
})();
相对于现有答案的优势(或区别):
异步 忽略符号链接 如果目录已经存在,则不抛出(如果不需要,则不捕获mkdir抛出) 相当简洁的
其他回答
下面是一个递归复制目录及其内容到另一个目录的函数:
const fs = require("fs")
const path = require("path")
/**
* 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 (isDirectory) {
fs.mkdirSync(dest);
fs.readdirSync(src).forEach(function(childItemName) {
copyRecursiveSync(path.join(src, childItemName),
path.join(dest, childItemName));
});
} else {
fs.copyFileSync(src, dest);
}
};
如果你在Linux上,性能不是问题,你可以使用child_process模块中的exec函数来执行一个Bash命令:
const { exec } = require('child_process');
exec('cp -r source dest', (error, stdout, stderr) => {...});
在某些情况下,我发现这个解决方案比下载整个模块甚至使用fs模块更简洁。
挑选包裹时要小心。有些包(如copy-dir)不支持复制长度超过0X1FFFFFE8个字符(约537 MB)的大文件。
它会抛出一些错误,比如:
buffer.js:630 Uncaught Error:不能创建大于0x1fffffe8字符的字符串
在我的一个项目中,我就经历过类似的事情。最终,我不得不改变我正在使用的包并调整大量代码。我想说,这不是一个很愉快的经历。
如果需要多个源副本和多个目标副本,您可以使用better-copy并编写如下内容:
// Copy from multiple source into a directory
bCopy(['/path/to/your/folder1', '/path/to/some/file.txt'], '/path/to/destination/folder');
甚至:
// Copy from multiple source into multiple destination
bCopy(['/path/to/your/folder1', '/path/to/some/file.txt'], ['/path/to/destination/folder', '/path/to/another/folder']);
由于我只是构建一个简单的Node.js脚本,我不希望脚本的用户需要导入一堆外部模块和依赖项,所以我开始思考,并从Bash shell中搜索运行命令。
这个Node.js代码片段递归地复制了一个名为node-webkit的文件夹。应用程序到一个名为build的文件夹:
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 {
}
});
感谢dzone的兰斯·波拉德让我开始。
上面的代码片段仅限于基于unix的平台,如macOS和Linux,但类似的技术也适用于Windows。
有一些模块支持复制文件夹及其内容。最流行的是wrench.js:
// 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