是否有一种更简单的方法来复制文件夹及其所有内容,而无需手动执行一系列的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+中可用
当前回答
我写了这个函数用于在目录之间递归地复制(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);
}
});
}
其他回答
这是我解决这个问题的方法,没有任何额外的模块。只使用内置的fs和path模块。
注意:这使用fs的读/写函数,所以它不复制任何元数据(创建时间等)。从Node.js 8.5开始,有一个copyFileSync函数可用,它调用操作系统复制函数,因此也复制元数据。我还没有测试它们,但它应该可以替换它们。(见https://nodejs.org/api/fs.html fs_fs_copyfilesync_src_dest_flags)
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 );
}
} );
}
}
支持符号链接的:
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);
}
});
}
我是这样做的:
let fs = require('fs');
let path = require('path');
然后:
let filePath = // Your file path
let fileList = []
var walkSync = function(filePath, filelist)
{
let files = fs.readdirSync(filePath);
filelist = filelist || [];
files.forEach(function(file)
{
if (fs.statSync(path.join(filePath, file)).isDirectory())
{
filelist = walkSync(path.join(filePath, file), filelist);
}
else
{
filelist.push(path.join(filePath, file));
}
});
// Ignore hidden files
filelist = filelist.filter(item => !(/(^|\/)\.[^\/\.]/g).test(item));
return filelist;
};
然后调用该方法:
This.walkSync(filePath, fileList)
挑选包裹时要小心。有些包(如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']);
有一些模块支持复制文件夹及其内容。最流行的是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