NodeJs 批量重命名文件,并保存到指定目录

源代码(file-rename.js)

// 文件路径:file-rename.js
/**
 * NodeJs 批量重命名文件,并保存到指定目录,支持递归目录
 * 功能:批量重命名文件,并保存到指定目录,支持递归目录
 * 使用:node file-rename.js
 * 扩展包:无
 */

// 引用 fs 文件系统模块
const NmFs = require('fs');
// 引用 path 路径处理模块
const NmPath = require('path');

// 配置信息
const config = {
    // 过滤字符串模式
    filter_text: {
        enable: false,
        text: '',
    },
    // 前面删除模式
    trim_start: {
        enable: true,
        // 删除指定的字符串
        text: '',
        // 删除 {length} 个字符
        length: 10,
        // 删除 {length} 必须包含的关键词
        length_key: 'NO.',
    },
    // 后面删除模式
    trim_end: {
        enable: false,
        // 删除指定的字符串
        text: '',
        // 删除 {length} 个字符
        length: 0
    },
    // 后面追加模式
    append: {
        enable: false,
        text: '-append',
    },
    // 前面追加件模式
    prepend: {
        enable: false,
        text: 'prepend-',
    },
    // 中间替换或插入模式
    splice: {
        enable: false,
        // 删除的开始位置
        start: 0,
        // 被删除的字符数量,数值 0 表示插入字符串
        length: 0,
        // 要替换或插入的字符串
        text: '',
    },
    // 允许处理的文件扩展名
    allow_exts: {
        enable: false,
        exts: ['jpg', 'png', 'gif', 'jpeg', 'webp', 'tiff'],
    },
    // 跳过处理的文件扩展名
    skip_exts: {
        enable: false,
        exts: []
    }
}

/**
 * 更改文件名
 * @param {String} basename 文件名,无扩展名
 * @param {String} ext 文件扩展名
 */
function changeName(basename = '', ext = '', isDirMode = false) {
    if (!isDirMode && ext) {
        if ((config.allow_exts.enable && !config.allow_exts.exts.includes(ext))) {
            return basename;
        }
        if (config.skip_exts.enable && config.skip_exts.exts.includes(ext)) {
            return basename;
        }
    }
    let nameLength = basename.length;
    // 文件名前面移除字符
    if (config.trim_start.enable) {
        // 字符串匹配删除模式
        if (config.trim_start.text.length > 0 && basename.indexOf(config.trim_start.text) > -1) {
            // basename = basename.substring(config.trim_start.text.length);
            basename = basename.replace(config.trim_start.text, '');
        }
        // 字符长度删除模式
        if (config.trim_start.length > 0 && (nameLength > config.trim_start.length)) {
            console.log(basename, config.trim_start.length_key, basename.indexOf(config.trim_start.length_key));
            if ((config.trim_start.length_key.length == 0) || (config.trim_start.length_key.length > 0 && basename.indexOf(config.trim_start.length_key) > 0)) {
                basename = basename.substring(config.trim_start.length);
            }
        }
    }
    // 文件名后面移除字符
    if (config.trim_end.enable) {
        // 字符串匹配删除模式
        if (basename.indexOf(config.trim_end.text) > -1) {
            // basename = basename.substring(0, nameLength - config.trim_end.text.length);
            basename = basename.replace(config.trim_end.text, '');
        }
        // 字符长度删除模式
        if (config.trim_end.length > 0 && nameLength > config.trim_end.length) {
            basename = basename.substring(0, nameLength - config.trim_end.length);
        }
    }
    // 过滤字符串模式
    if (config.filter_text.enable && config.filter_text.text.length > 0) {
        basename = basename.replace(new RegExp(config.filter_text.text, 'ig'), '');
    }
    // 中间替换或插入模式
    if (config.splice.enable) {
        let a = basename.substring(0, config.splice.start);
        let b = basename.substring(config.splice.start + config.splice.length);
        basename = a + config.splice.text + b;
    }
    // 文件名前面插入字符
    if (config.prepend.enable) {
        basename = config.prepend.text + basename;
    }
    // 文件名后面插入字符
    if (config.append.enable) {
        basename = basename + config.append.text;
    }
    return basename;
}

/**
 * 批量更改文件名到指定目录
 * @param {String} fromDir 来源目录
 * @param {String} toDir 目标目录
 * @param {Boolean} isDebug 是否调试模式。调试模式不会执行重命名操作,只会输出控制台日志
 * @param {Boolean} isSkipExists 是否跳过已存在的目标文件
 * @param {Boolean} isDirMode 是否重命名对象为目录,否则为文件
 * @param {Boolean} isRecursion 是否递归遍历子目录
 */
async function renameFiles(fromDir, toDir, isDebug = true, isSkipExists = true, isDirMode = false, isRecursion = true) {
    if (!NmFs.existsSync(fromDir)) {
        console.log('path not exists: ', fromDir);
        return;
    }
    // 自动创建目标路径
    if (!isDebug && !NmFs.existsSync(toDir)) {
        NmFs.mkdirSync(toDir, {
            recursive: true
        });
    }
    let sep = NmPath.sep;
    // 自动补齐路径符
    if (!fromDir.endsWith(sep)) {
        fromDir += sep;
    }
    if (!toDir.endsWith(sep)) {
        toDir += sep;
    }
    // 打开目录
    const dir = await NmFs.promises.opendir(fromDir);
    // 声明变量,优化内存
    let basename = '',
        ext = '',
        newPath = '',
        currentPath = '';
    for await (const dirent of dir) {
        // 当前路径
        currentPath = fromDir + dirent.name;
        newPath = toDir + dirent.name;
        // 处理目录
        if (dirent.isDirectory()) {
            // 如果当前路径是目录,则进入递归模式
            if (isDirMode) {
                ext = '';
                basename = NmPath.basename(dirent.name, ext); // 无扩展名
                basename = changeName(basename, ext);
                newPath = toDir + basename;
                // 判断是否过滤已存在的目标文件
                if (isSkipExists && NmFs.existsSync(newPath)) {
                    console.log('[已存在]', currentPath, '=>', newPath);
                    continue;
                }
                if (!isDebug) {
                    NmFs.renameSync(currentPath, newPath);
                }
                console.log('[重命名]', currentPath, '=>', newPath);
            }
            if (isRecursion) {
                renameFiles(currentPath + sep, newPath + sep, isDebug, isSkipExists, isDirMode, isRecursion);
            }
            continue;
        }
        if (isDirMode) {
            continue;
        }
        // 文件名
        ext = NmPath.extname(dirent.name); // .jpg
        basename = NmPath.basename(dirent.name, ext); // 无扩展名
        ext = ext.substring(1).toLowerCase();
        basename = changeName(basename, ext);
        newPath = toDir + basename + '.' + ext;
        // 判断是否过滤已存在的目标文件
        if (isSkipExists && NmFs.existsSync(newPath)) {
            console.log('[已存在]', currentPath, '=>', newPath);
            continue;
        }
        if (!isDebug) {
            NmFs.renameSync(currentPath, newPath);
        }
        console.log('[重命名]', currentPath, '=>', newPath);
    }
}

// 执行批量文件重命名功能
const FROM_DIR = 'F:\\Downloads\\Images';
const TO_DIR = FROM_DIR;
const IS_DEBUG = false;
const IS_SKIP_EXISTS = true;
const IS_DIR_MODE = true;
const IS_RECURSION = false;
renameFiles(FROM_DIR, TO_DIR, IS_DEBUG, IS_SKIP_EXISTS, IS_DIR_MODE, IS_RECURSION).catch(err => console.log(err))

运行文件

node file-rename.js
posted on 2021-01-17 20:33  sochishun  阅读(787)  评论(0编辑  收藏  举报