批量重命名具有多个不等宽度的文件

批量重命名具有多个不等宽度的文件

我有类似的文件

file1.txt
file2.txt
file3.txt
...
file11.txt
file12.txt
...
file100.txt
file101.txt
...

我想将它们重命名为具有相同的字符串宽度,例如

file001.txt
file002.txt
file003.txt
...
file011.txt
file012.txt
...
file100.txt
file101.txt
...

有没有一个简单的命令可以实现这一目标?我想避免手动重命名,例如使用 Rangerbulkrename。

答案1

在手册页中rename(1),您可以查看一个示例来执行此操作:

EXAMPLES
       Given the files foo1, ..., foo9, foo10, ..., foo278, the commands

              rename foo foo00 foo?
              rename foo foo0 foo??

       will turn them into foo001, ..., foo009, foo010, ..., foo278

因此,对于您的情况,简单的解决方案(如果最大数字为 3 位数长)将是:

rename file file00 file?.txt
rename file file0 file??.txt

在运行实际命令之前,您可以通过添加和标志rename来测试它,看看结果是什么:--no-act / -n--verbose / -v

$ rename -nv file file00 file?.txt
`file1.txt' -> `file001.txt'
`file2.txt' -> `file002.txt'
`file3.txt' -> `file003.txt'
$ rename -nv file file0 file??.txt
`file11.txt' -> `file011.txt'
`file12.txt' -> `file012.txt'

更通用的解决方案(从bash3.0 版本开始可用):

$ for i in `find ./ -maxdepth 1 -type f -name 'file*.txt'`; \
  do if [[ "$i" =~ file([0-9]*).txt$ ]]; \
    then NUM=$(printf "%03d" "${BASH_REMATCH[1]}"); \
    echo mv --verbose $i $i ./file${NUM}.txt; \
  fi; \
done
mv --verbose ./file1.txt ./file001.txt
mv --verbose ./file2.txt ./file002.txt
mv --verbose ./file3.txt ./file003.txt
mv --verbose ./file11.txt ./file011.txt
mv --verbose ./file12.txt ./file012.txt
mv --verbose ./file100.txt ./file100.txt
mv --verbose ./file101.txt ./file101.txt

echo当您想要执行更改时删除。这只是一个简单的示例,您也可以在行中将文件的前缀和后缀更改为模式if,并使用$BASH_REMATCH捕获这些模式来进行更复杂的重命名。例如:

$ for i in `find ./ -maxdepth 1 -type f`; \
  do if [[ "$i" =~ ^([^0-9]*)([0-9]*).txt$ ]]; \
    then NUM=$(printf "%03d" "${BASH_REMATCH[2]}"); \
    echo mv --verbose $i ${BASH_REMATCH[1]}${NUM}.txt; \
  fi; \
done
mv --verbose ./file1.txt ./file001.txt
mv --verbose ./file2.txt ./file002.txt
mv --verbose ./file3.txt ./file003.txt
mv --verbose ./file11.txt ./file011.txt
mv --verbose ./file12.txt ./file012.txt
mv --verbose ./file100.txt ./file100.txt
mv --verbose ./file101.txt ./file101.txt
mv --verbose ./something1.txt ./something001.txt
mv --verbose ./another02.txt ./another002.txt

当然,您可以修改printf命令,将零填充长度从 3 更改为任何其他数字。

答案2

要将所有 ASCII 十进制数字序列的文件重命名为宽度为 3(带 0)的文件,请使用zsh

autoload -Uz zmv
zmv -n '*' '${f//(#m)<->/${(l[3][0])MATCH}}'

-n如果对结果满意,请删除进行试运行)。

与基于 Perl 的rename实现相同(有时称为file-rename,prenameperl-rename):

rename -n 's/\d+/sprintf "%03d", $&/ge' ./*[0123456789]*

答案3

使用 perlrename实用程序,也称为file-renameperl-renameprename。不要将其与具有完全不同且不兼容的功能和命令行选项的rename实用程序混淆。 util-linuxPerl 重命名允许您使用任意复杂的 Perl 代码来重命名文件,但最常用于对文件名执行简单的sed类似s/search/replace/操作。

rename -n 's/^file(\d+)\.txt$/sprintf "file%03i.txt", $1/e' file*.txt

regex修饰符/e告诉 rename 将 s/search/replace/ 运算符的替换部分视为可执行的 perl 代码。该sprintf函数用于对 .txt 扩展名之前的数字进行零填充。

或者它可以推广到任何文件名前缀和扩展名 - 例如

rename -n 's/\A(.*?)(\d+)(\..*)\z/sprintf "%s%03i%s", $1, $2, $3/esm' *

/s和正/m则表达式修饰符用于确保脚本适用于任何文件名,甚至包含换行符的文件名。 \A是字符串开头锚点,也是\z字符串结尾锚点。

请注意,该-n选项使其成为一次试运行,因此它只会显示它将执行的操作,而不会实际重命名任何文件。当您确认它符合您的要求后,请删除-n,或将其替换为 以获得详细输出。-v

相关内容