深入了解 Linux 文件重命名的强大功能,让 `mv` 命令稍作休息。掌握更灵活、快捷,有时甚至更简单的重命名方法。本教程将带你探索这个强大工具的奥秘。
`mv` 命令的局限性
`mv` 命令本身并没有任何问题。 它确实非常有效,并且存在于所有 Linux 发行版、macOS 和其他类 Unix 操作系统中。这意味着它总是可以被使用。但有时,我们需要的不仅仅是铲子,而是推土机般的效率。
`mv` 命令的主要用途是移动文件。它也可以将现有文件移动到具有新名称的新文件中,但这只是一个”副作用”。虽然最终效果确实是重命名文件,但 `mv` 并非专门为文件重命名而设计的工具。
使用 `mv` 重命名单个文件
要使用 `mv` 重命名单个文件,只需输入 `mv`、空格、原文件名、空格,然后输入你想要的新文件名,最后按回车键即可。
你可以使用 `ls` 命令检查文件是否已被成功重命名。
mv oldfile.txt newfile.txt
ls *.txt
使用 `mv` 重命名多个文件
当你需要重命名多个文件时,情况会变得复杂起来。 `mv` 命令本身并不支持一次性重命名多个文件。 你需要借助一些 Bash 技巧才能实现。如果你对命令行操作有一定了解,这可能会容易一些,但使用 `mv` 重命名多个文件的复杂性与使用它重命名单个文件的简洁性形成了鲜明对比。
情况会迅速升级。
假设我们有一个目录,其中包含各种类型的文件,其中一些文件具有 `.prog` 扩展名。 我们希望通过命令行将它们重命名为 `.prg` 扩展名。
如何让 `mv` 为我们做到这一点呢? 首先让我们列出这些文件。
ls *.prog -l
下面是一种不需要编写实际 Bash 脚本文件的方法。
for f in *.prog; do mv -- "$f" "${f%.prog}.prg"
这是否有效?让我们检查一下文件。
ls *.pr*
是的,它成功了。所有文件现在都是 `.prg` 文件,并且目录中不再有 `.prog` 文件。
刚才发生了什么?
那个长长的命令到底做了什么呢?让我们来分解一下。
for f in *.prog; do mv -- "$f" "${f%.prog}.prg"
第一部分 `for f in *.prog` 开始一个循环,它会依次处理目录中每个 `.prog` 文件。
下一部分 `do mv — “$f” “${f%.prog}.prg”` 说明了循环中要执行的操作。 它使用 `mv` 命令将每个文件移动到新文件。 新文件的名称与原始文件名相同,只是删除了 `.prog` 部分,并使用了新的 `.prg` 扩展名。
一定有更简单的方法
确实如此。那就是 `rename` 命令。
`rename` 命令并非标准 Linux 发行版的一部分,因此你需要安装它。在不同的 Linux 发行版中,它的名称可能会有所不同,但它们的工作方式基本相同。你只需要根据你使用的 Linux 发行版替换正确的命令名称即可。
在基于 Ubuntu 和 Debian 的发行版中,你可以使用以下命令安装 `rename`:
sudo apt-get install rename
在基于 Fedora 和 RedHat 的发行版中,你可以使用以下命令安装 `prename`。 请注意开头的 “p”,它代表 Perl。
sudo dnf install prename
在 Manjaro Linux 中安装它,你需要使用以下命令。 请注意,此处的 `rename` 命令称为 `perl-rename`。
sudo pacman -Syu perl-rename
让我们再做一次
这次我们将使用 `rename` 命令。 我们先恢复到之前的状态,确保我们有一组 `.prog` 文件。
ls *.prog
现在,让我们使用以下命令重命名这些文件。 然后我们使用 `ls` 命令验证结果。 请记住,如果你使用的不是基于 Ubuntu 或 Debian 的 Linux,你需要将 `rename` 替换为适合你的发行版的命令名称。
rename 's/.prog/.prg/' *.prog
ls *.pr*
它成功了,所有文件现在都是 `.prg` 文件,并且目录中不再有 `.prog` 文件。
这次发生了什么?
让我们将这个命令分解为三个部分来解释它的工作原理。
第一部分是命令名 `rename`(或 `prename` 或 `perl-rename`,取决于你的发行版)。
最后一部分是 `*.prog`,它告诉 `rename` 命令对所有 `.prog` 文件执行操作。
中间部分定义了我们将对每个文件名执行的操作。 `s` 表示替换。 第一项 (`.prog`) 是 `rename` 命令将在每个文件名中搜索的内容,而第二项 (`.prg`) 是将被替换的内容。
命令的中间部分或核心表达式实际上是 Perl 正则表达式。这正是赋予 `rename` 命令强大灵活性的原因。
更改文件名的其他部分
到目前为止,我们已经更改了文件扩展名,现在让我们修改文件名的其他部分。
假设我们目录中有很多 C 源代码文件。所有文件名的前缀都是 `slang_`。我们可以使用 `ls` 命令进行验证。
ls sl*.c
我们将把所有出现的 `slang_` 替换为 `sl_`。 命令的格式我们已经熟悉了。 我们只需要更改搜索词、替换词和文件类型。
rename 's/slang_/sl_/' *.c
这次我们查找的是 `.c` 文件,并搜索 `slang_`。 只要在文件名中找到 `slang_`,它就会被 `sl_` 替换。
我们可以通过使用相同的参数从上面重复 `ls` 命令来验证命令结果:
ls sl*.c
删除文件名的一部分
我们可以通过将搜索词替换为空字符串来删除文件名的一部分。
ls *.c
rename 's/sl_//' *.c
ls *.c
我们可以从 `ls` 命令的输出中看到,我们所有的 `.c` 文件名都以 `sl_` 开头。 现在,我们完全删除它。
`rename` 命令的格式与之前相同。 我们将查找 `.c` 文件。 搜索词是 `sl_`,但是没有替代词。两个斜杠之间什么都没有,这代表一个空字符串。
`rename` 命令将依次处理每个 `.c` 文件。 它将在文件名中查找 `sl_`。 如果找到,它将被替换为空字符串。换句话说,搜索词将被删除。
第二次使用 `ls` 命令证实了 `sl_` 前缀已从每个 `.c` 文件名中删除。
限制对文件名特定部分的更改
让我们使用 `ls` 命令列出文件名中包含字符串 `param` 的文件。 然后,我们将使用 `rename` 命令将该字符串替换为 `parameter`。 我们再次使用 `ls` 命令查看 `rename` 命令对这些文件的影响。
ls *param*
rename 's/param/parameter/' *.c
ls *param*
找到了四个文件名中包含 `param` 的文件。 `param.c`、`param_one.c` 和 `param_two.c` 的名称都以 `param` 开头。`third_param.c` 的名称末尾包含 `param`,紧接在扩展名之前。
`rename` 命令将在文件名中的所有位置搜索 `param`,并在所有情况下将其替换为 `parameter`。
第二次使用 `ls` 命令显示了实际发生的情况。 不管 `param` 位于文件名的开头还是结尾,它都被替换为 `parameter`。
我们可以使用 Perl 的元字符来改进中间表达式的行为。 元字符是表示字符位置或序列的符号。 例如, `^` 表示“字符串的开头”, `$` 表示“字符串的结尾”,而 `.` 表示任何单个字符(除了换行符)。
我们将使用字符串开头元字符 (`^`) 将搜索限制在文件名的开头。
ls *param*.c
rename 's/^parameter/value/' *.c
ls *param*.c
ls value*.c
列出了我们之前重命名的文件。我们可以看到字符串 `parameter` 位于三个文件名的开头,其中一个文件名的末尾。
我们的重命名命令在搜索词 `parameter` 之前使用行首 (`^`) 元字符。 这告诉 `rename` 命令只考虑在文件名开头找到的搜索词。 如果搜索字符串 `parameter` 位于文件名中的其他位置,则会被忽略。
通过 `ls` 命令的验证,我们可以看到文件名末尾包含 `parameter` 的文件没有被修改。但是,开头包含 `parameter` 的三个文件名已经将搜索字符串替换为 `value`。
`rename` 命令的强大之处在于 Perl 的力量。你能够随时使用 完整的 Perl 功能。
分组搜索
`rename` 命令还有更多技巧。让我们考虑文件名中可能包含相似字符串的情况。 它们不是完全相同的字符串,因此简单的搜索和替换在这里无法发挥作用。
在此示例中,我们使用 `ls` 命令列出所有以 `str` 开头的文件。其中有两个文件:`string.c` 和 `strangle.c`。我们可以使用称为分组的技术一次性重命名这两个字符串。
此 `rename` 命令的中心表达式将在文件名中搜索字符序列 `stri` 或 `stra`,并且后面紧跟着 `ng` 的字符串。换句话说,我们的搜索词将查找 `string` 和 `strang`。 替换词是 `bang`。
ls str*.c
rename 's/(stri|stra)ng/bang/' *.c
ls ban*.c
再次使用 `ls` 命令进行确认, `string.c` 已经变为 `bang.c`,而 `strangle.c` 现在是 `bangle.c`。
使用 rename 命令进行翻译
`rename` 命令还可以对文件名执行称为翻译的操作。一个简单的翻译示例是将一组文件名全部转换为大写。
请注意,在下面的 `rename` 命令中,我们没有使用 `s/` 来启动中心表达式,而是使用了 `y/`。 这告诉 `rename` 命令我们不是在执行替换,而是在进行翻译。
`az` 术语是一个 Perl 表达式,表示从 `a` 到 `z` 序列中的所有小写字符。 同样, `AZ` 术语表示从 `A` 到 `Z` 序列中的所有大写字母。
此命令的中心表达式可以解释为: “如果在文件名中找到任何从 `a` 到 `z` 的小写字母,则将其替换为从 `A` 到 `Z` 的大写字符序列中的相应字符。”
要将所有 `.prg` 文件的文件名强制转换为大写,请使用以下命令:
rename ‘y/az/AZ/’ *.prg
ls *.PRG
`ls` 命令显示所有 `.prg` 文件名现在都是大写的。事实上,严格来说,它们不再是 `.prg` 文件了。它们是 `.PRG` 文件。 Linux 是区分大小写的。
我们可以通过反转中心表达式中 `az` 和 `AZ` 术语的位置来反转最后一次操作。
rename ‘y/AZ/az/’ *.PRG
ls *.prg
你无需在五分钟内精通 Perl
掌握 Perl 当然值得。但是,要开始使用 `rename` 命令的省时功能,你并不需要太多的 Perl 知识,便可以在功能、简易性和时间方面获得巨大的回报。