是否有一种更简单的方法来复制文件夹及其所有内容,而无需手动执行一系列的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+中可用
当前回答
支持符号链接的:
const path = require("path");
const {
existsSync,
mkdirSync,
readdirSync,
lstatSync,
copyFileSync,
symlinkSync,
readlinkSync,
} = require("fs");
export function copyFolderSync(src, dest) {
if (!existsSync(dest)) {
mkdirSync(dest);
}
readdirSync(src).forEach((entry) => {
const srcPath = path.join(src, entry);
const destPath = path.join(dest, entry);
const stat = lstatSync(srcPath);
if (stat.isFile()) {
copyFileSync(srcPath, destPath);
} else if (stat.isDirectory()) {
copyFolderSync(srcPath, destPath);
} else if (stat.isSymbolicLink()) {
symlinkSync(readlinkSync(srcPath), destPath);
}
});
}
其他回答
下面是一个递归复制目录及其内容到另一个目录的函数:
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/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}`);
就是这样!
fs-extra模块工作起来很有魅力。
安装fs-extra:
$ npm install fs-extra
下面是将源目录复制到目标目录的程序。
// Include the fs-extra package
var fs = require("fs-extra");
var source = 'folderA'
var destination = 'folderB'
// Copy the source folder to the destination
fs.copy(source, destination, function (err) {
if (err){
console.log('An error occurred while copying the folder.')
return console.error(err)
}
console.log('Copy completed!')
});
参考文献
fs-extra: https://www.npmjs.com/package/fs-extra
示例:Node.js教程- Node.js复制文件夹
挑选包裹时要小心。有些包(如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']);
这可能是一个可能的解决方案使用异步生成器函数和迭代等待循环。这个解决方案包括过滤掉一些目录的可能性,将它们作为可选的第三个数组参数传递。
import path from 'path';
import { readdir, copy } from 'fs-extra';
async function* getFilesRecursive(srcDir: string, excludedDir?: PathLike[]): AsyncGenerator<string> {
const directoryEntries: Dirent[] = await readdir(srcDir, { withFileTypes: true });
if (!directoryEntries.length) yield srcDir; // If the directory is empty, return the directory path.
for (const entry of directoryEntries) {
const fileName = entry.name;
const sourcePath = resolvePath(`${srcDir}/${fileName}`);
if (entry.isDirectory()) {
if (!excludedDir?.includes(sourcePath)) {
yield* getFilesRecursive(sourcePath, excludedDir);
}
} else {
yield sourcePath;
}
}
}
然后:
for await (const filePath of getFilesRecursive(path, ['dir1', 'dir2'])) {
await copy(filePath, filePath.replace(path, path2));
}