文件批量重命名的三重境界

719 阅读2分钟

今天项目遇到了一个批量重命名某个目录下所有文件的需求,发现大家处理的方式完全不一样:

普通工程师

在 Mac 下批量重命名文件是非常方便的,只要批量选择所有文件,右键「重新命名」就会弹出来一个输入框,选择匹配规则,然后输入替换文字即可,例如将 1.jpeg ~ 3.jpeg 的后缀全改成 .png,就可以这么操作:

那如果想递归更改某个目录下所有指定后缀的文件该如何操作呢?例如:把 src 目录下所有 .ts 后缀文件都改成 .js,这种方式就无能为力了。

高级工程师

先安装 rename,然后一行代码搞定:

brew install rename
find . -type f -name "*.ts" -print | xargs rename 's/\.ts/\.js/'

如果只是想查看替换效果,不真正替换的话,可以添加 -n 参数,例如:

$ find . -type f -name "*.ts" -print | xargs rename -n 's/\.ts/\.js/'
'./order.class.ts' would be renamed to './order.class.js'
'./order.service.ts' would be renamed to './order.service.js'
'./order.hooks.ts' would be renamed to './order.hooks.js'

资深工程师

那如果还有更复杂的规则,只能写脚本了,可以用任何语言例如 nodejs、python、java、go 等。例如用 node.js 写一个 rename 函数,把指定文件夹下面所有文件或文件夹都加上一个前缀,代码如下:

const fs = require("fs")
const path = require('path')

function rename(dir, prefix = 'rename_') {
  fs.readdir(dir, (e, files) => {
    for (let i = 0; i < files.length; i++) {
      let f = files[i]
      fs.rename(path.join(dir, f), path.join(dir, prefix + f), (err) => {
        if (err) throw err
        console.log(f + ' --> ' + prefix + f)
      })
    }
  })
}
rename(__dirname)

不过这个例子还是太简单了,对于复杂重命名的需求,就要用到之前讲过的 glob 语法了,例如想找到 src 目录下所有 js 和 jsx 文件,3 行代码搞定:

const glob = require('glob')
const files = glob.sync('src/**/*.js{,x}')
console.log(files)

既然拿到了文件的绝对路径,接下来就简单了,直接调用 fs.rename 方法替换成你想要的名称即可。不过建议大家在重命名的时候,配合 Git 一起使用,一旦出现错误能够及时发现并回滚:

git checkout . && git clean -xdf