是否有一种更简单的方法来复制文件夹及其所有内容,而无需手动执行一系列的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+中可用
当前回答
这可能是一个可能的解决方案使用异步生成器函数和迭代等待循环。这个解决方案包括过滤掉一些目录的可能性,将它们作为可选的第三个数组参数传递。
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));
}
其他回答
如果你在Linux上,性能不是问题,你可以使用child_process模块中的exec函数来执行一个Bash命令:
const { exec } = require('child_process');
exec('cp -r source dest', (error, stdout, stderr) => {...});
在某些情况下,我发现这个解决方案比下载整个模块甚至使用fs模块更简洁。
我创建了一个小的工作示例,只需几个步骤就可以将源文件夹复制到另一个目标文件夹(基于shift66使用ncp的答案):
步骤1 -安装ncp模块:
npm install ncp --save
步骤2 -创建copy.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.');
});
第三步——跑步
node copy.js
目前最上面的答案可以大大简化。
const path = require('path');
const fs = require('fs');
function recursiveCopySync(source, target) {
if (fs.lstatSync(source).isDirectory()) {
if (!fs.existsSync(target)) {
fs.mkdirSync(target);
}
let files = fs.readdirSync(source);
files.forEach((file) => {
recursiveCopySync(path.join(source, file), path.join(target, file));
});
} else {
if (fs.existsSync(source)) {
fs.writeFileSync(target, fs.readFileSync(source));
}
}
}
我写了这个函数用于在目录之间递归地复制(copyFileSync)或移动(renameSync)文件:
// Copy files
copyDirectoryRecursiveSync(sourceDir, targetDir);
// Move files
copyDirectoryRecursiveSync(sourceDir, targetDir, true);
function copyDirectoryRecursiveSync(source, target, move) {
if (!fs.lstatSync(source).isDirectory())
return;
var operation = move ? fs.renameSync : fs.copyFileSync;
fs.readdirSync(source).forEach(function (itemName) {
var sourcePath = path.join(source, itemName);
var targetPath = path.join(target, itemName);
if (fs.lstatSync(sourcePath).isDirectory()) {
fs.mkdirSync(targetPath);
copyDirectoryRecursiveSync(sourcePath, targetPath);
}
else {
operation(sourcePath, targetPath);
}
});
}
这可能是一个可能的解决方案使用异步生成器函数和迭代等待循环。这个解决方案包括过滤掉一些目录的可能性,将它们作为可选的第三个数组参数传递。
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));
}