一、复制文件或文件夹

1.同步复制
const fs = require('fs'); //文件模块
const path = require('path'); //系统路径模块

/**
 * 同步复制文件或文件夹
 * @param {String} fromPath 源始路径,参数可以是文件或文件夹
 * @param {String} toPath 目标路径,参数可以是文件或文件夹
 */
function copyFileSync(fromPath, toPath, cb) {
    try {
        fs.accessSync(toPath);
    } catch (err) {
        fs.mkdirSync(toPath)
    }

    const filenames = fs.readdirSync(fromPath);
    filenames.forEach((filename) => {
        const newFromPath = path.join(fromPath, filename);
        const newToPath = path.join(toPath, filename);
        const stat = fs.statSync(newFromPath);

        if (stat.isFile()) {
            fs.copyFileSync(newFromPath, newToPath);
        }
        if (stat.isDirectory()) {
            copyFileSync(newFromPath, newToPath, cb);
        }
    })
}

应用示例:复制文件夹a到b

const path = require('path'); //系统路径模块
const pathA = path.join(__dirname, './a');
const pathB = path.join(__dirname, './b');
copyFileSync(pathA, pathB);
2.异步复制
/**
 * 异步复制文件或文件夹
 * @param {*} fromPath 源始路径,参数可以是文件或文件夹
 * @param {*} toPath 目标路径,参数可以是文件或文件夹
 */
function copyFile(fromPath, toPath) {
    return new Promise((resolve, reject) => {
        fs.access(fromPath, err => {
            if (err) reject(err)
            fs.stat(fromPath, (err, stats) => {
                //如果是文件
                if (stats.isFile()) {
                    fs.copyFile(fromPath, toPath, (err) => {
                        err ? reject(err) : resolve();
                    });
                } else {
                    fs.access(toPath, err => {
                        // 如果不存在则创建
                        new Promise((resv, rejt) => {
                            err ? fs.mkdir(toPath, err => (err ? rejt(err) : resv())) : resv();
                        }).then(() => {
                            fs.readdir(fromPath, (err, filenames) => {
                                if (err) reject(err)
                                Promise.all(filenames.map(filename => {
                                    return new Promise((res, rej) => {
                                        let newFromPath = path.join(fromPath, filename)
                                        let newToPath = path.join(toPath, filename)
                                        fs.stat(newFromPath, (err, stats) => {
                                            if (err) rej(err)
                                                //如果是文件
                                            if (stats.isFile()) {
                                                fs.copyFile(newFromPath, newToPath, (err) => {
                                                    err ? rej(err) : res();
                                                });
                                            } else {
                                                //如果是目录递归调用
                                                res(copyFile(newFromPath, newToPath))
                                            }
                                        })
                                    });
                                })).then(() => {
                                    resolve()
                                }).catch(reject);
                            });
                        }).catch(reject);
                    });
                }
            });
        })
    })
}

应用示例:复制文件夹a到b

const path = require('path'); //系统路径模块
const pathA = path.join(__dirname, './a');
const pathB = path.join(__dirname, './b');

copyFile(pathA, pathB).then((resolve) => {
    console.log('复制成功');
}).catch(e => {
    console.log(e)
});

二、删除文件或文件夹

1.同步删除
const fs = require('fs'); //文件模块
const path = require('path'); //系统路径模块

**
 * 同步删除文件或文件夹
 * @param {String} filePath 文件路径,参数可以是文件或文件夹
 */
function deleteFileSync(filePath) {
    // 检测文件是否存在
    if (fs.existsSync(filePath)) {
        // 检测文件是目录
        if (fs.statSync(filePath).isDirectory()) {
            // 获取目录内所有文件名
            const filenames = fs.readdirSync(filePath);
            filenames.forEach((filename) => {
                const currentPath = path.join(filePath, filename);
                if (fs.statSync(currentPath).isDirectory()) {
                    deleteFileSync(currentPath);
                } else {
                    fs.unlinkSync(currentPath);
                }
            });
            fs.rmdirSync(filePath);
        } else {
            fs.unlinkSync(filePath);
        }
    }
}

应用示例:删除文件夹a

const path = require('path'); //系统路径模块
const pathA = path.join(__dirname, './a');
delFile(pathA);
2.异步删除
const fs = require('fs'); //文件模块
const path = require('path'); //系统路径模块
/**
 * 异步删除文件或文件夹
 * @param {String} filePath 文件路径,参数可以是文件或文件夹
 */
function deleteFile(filePath) {
    return new Promise((resolve, reject) => {
        fs.access(filePath, err => {
            if (err) reject(err)
            fs.stat(filePath, (err, stats) => {
                if (err) reject(err)
                if (stats.isFile()) {
                    fs.unlink(filePath, err => {
                        if (err) reject(err)
                        resolve()
                    })
                } else {
                    fs.readdir(filePath, (err, filenames) => {
                        if (err) reject(err)
                        Promise.all(filenames.map(filename => {
                            return new Promise((res, rej) => {
                                let currentPath= path.join(filePath, filename)
                                fs.stat(currentPath, (err, stats) => {
                                    if (err) rej(err)
                                        //如果是文件
                                    if (stats.isFile()) {
                                        fs.unlink(currentPath, err => {
                                            if (err) rej(err)
                                            res()
                                        })
                                    } else {
                                        //如果是目录递归调用
                                        res(deleteFile(currentPath))
                                    }
                                })
                            })
                        })).then(() => {
                            fs.rmdir(filePath, err => {
                                if (err) reject(err)
                                resolve()
                            })
                        }).catch(reject)
                    })
                }
            });
        })
    })
}

应用示例:删除文件夹a

const path = require('path'); //系统路径模块
const pathA = path.join(__dirname, './a');
deleteFile(pathA).then((resolve) => {
    console.log('删除成功');
}).catch(e => {
    console.log(e)
});
3.异步删除(拆分成两个方法)
const fs = require('fs'); //文件模块
const path = require('path'); //系统路径模块

function deleteDirectory(dirPath){
    return new Promise((resolve,reject)=>{
        fs.access(dirPath,err=>{
            if(err)reject(err)
            fs.readdir(dirPath,(err,files)=>{
                if(err)reject(err)
                Promise.all(files.map(file=>{
                    return deleteFile(dirPath,file)
                })).then(()=>{
                    fs.rmdir(dirPath,err=>{
                        if(err)reject(err)
                        resolve()
                    })
                }).catch(reject)
            })
        })
    })
}

function deleteFile(dirPath,file){
    return new Promise((resolve,reject)=>{
        let filePath = path.join(dirPath,file)
        fs.stat(filePath,(err,stats)=>{
            if(err)reject(err)
            if(stats.isFile()){
                fs.unlink(filePath,err=>{
                    if(err)reject(err)
                    resolve()
                })
            }else{
                //返回deleteDirectory在all中递归调用
                resolve(deleteDirectory(filePath))
            }
        })
    })
}

应用示例:删除文件夹a

const path = require('path'); //系统路径模块
const pathA = path.join(__dirname, './a');
deleteDirectory(pathA).then((resolve) => {
    console.log('删除成功');
}).catch(e => {
    console.log(e)
});

三、替换文件内容

1.同步替换
/**
 * 同步替换文件内容
 * @param {String} filePath 文件路径
 * @param {*} oldContent 原始内容
 * @param {*} newContent 新内容
 * @param {String} suffix 后缀名,多个中间以|分隔
 */
function replaceFileSync(filePath, oldContent, newContent, suffix) {
    // 文件存在且类型是文件
    if (fs.existsSync(filePath) && fs.statSync(filePath).isFile() && oldContent && newContent) {
        // 获取路径后缀并去除前面的点
        let ext = path.extname(filePath);
        ext = ext ? ext.slice(1) : '';

        // 如果没有指定后缀,或者指定了后缀且匹配路径后缀,执行替换
        if (!suffix || (suffix.includes(ext))) {
            const data = fs.readFileSync(filePath); // 读取文件
            const content = data.toString().replace(oldContent, newContent); // 将原始内容替换为新内容
            fs.writeFileSync(filePath, content); // 写入文件
        }
    }
}

应用示例:替换文件夹a内容1111为2222

const path = require('path'); //系统路径模块
const pathA = path.join(__dirname, './a');
replaceFileSync(pathA, '1111', '2222', 'html|txt');