如何通过替换文件/目录名称中的片段来批量重命名许多文件和/或f o o
目录b a r
?
对于每种建议的方法,最好回答以下问题。
- 是否可以在进行实际重命名之前预览命令的结果?如何?
- 该方法是否仅适用于前缀,仅适用于后缀,还是不适用?
- 重命名是只影响目录、只影响文件,还是同时影响目录和文件?
- 子目录中的文件/目录也会被重命名吗?
替换前缀,示例
为了使任务更具体一点,假设文件
o l d prefix file 1.c
o l d prefix file 1.h
o l d prefix file 2.c
o l d prefix file 2.h
应该重命名为
n e w prefix file 1.c
n e w prefix file 1.h
n e w prefix file 2.c
n e w prefix file 2.h
还假设在同一目录中有(子)目录名为
o l d prefix, dir 1 _
o l d prefix, dir 2 _
这些目录也会被重命名吗?
你能调整你的方法来只重命名目录(而不是文件)吗?
或者只重命名文件(而不是目录)?
替换后缀
还可以考虑重命名文件中的后缀,以便将
file 1, o l d suffix
andfile 2, o l d suffix
分别重命名为
file 1, n e w suffix
and file 2, n e w suffix
。
对于目录也是如此。
dir 1., o l d suffix
将和分别重命名dir 2., o l d suffix
为
dir 1., n e w suffix
和dir 2., n e w suffix
。
推荐的方法?
你会推荐什么重命名方法?
笔记
请注意,向名称添加前缀或后缀只是更通用替换前缀或后缀的一种特殊情况,即原始前缀或后缀恰好是空字符串的情况。类似地,去除前缀或后缀的情况也是替换前缀或后缀的一种特殊情况,即新的前缀或后缀为空字符串的情况。
更多需要考虑的问题
我知道在重命名文件时还需要考虑其他更高级的问题,例如添加或删除日期或序列号和/或以下参考文献中最后五个问题中的主题。
我邀请您提出有关重命名文件/目录(或符号链接)的任何问题,并在您的答案中构建一个合适的示例。
写答案时,不要觉得你必须回答这里提出的所有案例!如果您愿意,请
随意只关注一个特定案例(上述案例之一,或您选择的其他案例)。
0. 针对通用解决方案1
为了方便我未来的自己和其他读者,我将专注于通用解决方案。
为简单起见,我假设在任何文件/目录名称 中都没有引号——没有双引号 (
"
) 和单引号 ( )。2'
作为第一个示例,我将展示如何使用模式重命名文件
o l d prefix file *.*
ton e w prefix file *.*
,从而即使文件名中有空格也可以重命名前缀。
我也对重命名目录感兴趣,因此会考虑将目录
o l d prefix, dir 1 _
和分别重命名o l d prefix, dir 2 _
为n e w prefix, dir 1 _
和n e w prefix, dir 2 _
。其次,我将展示如何替换后缀。例如,文件
file 1, o l d suffix
和file 2, o l d suffix
分别重命名为file 1, n e w suffix
和file 2, n e w suffix
。同样,我想看看这如何影响(或不影响)目录。
因此,我还将检查目录
dir 1., o l d suffix
和是否dir 2., o l d suffix
分别重命名为dir 1., n e w suffix
和dir 2., n e w suffix
。 3所有上述文件和目录都可以在 zip 文件中找到:http:
//user.it.uu.se/~hesc0353/Files-&-dirs-SEunix-A690768.zip。 4
笔记。
以下
echo
解决方案中出现 表示不会发生重命名。这是一种在您决定进行重命名之前预览重命名 的既定技术。 一旦预览看起来正常,只需删除并再次运行命令以执行实际重命名。 5
echo
1. 使用 for 循环的通用解决方案
重命名前缀意味着替换
o l d prefix
为n e w prefix
: 6我选择搜索以 . 开头的文件
o l d pref
。要重命名后缀,请尝试:
– 此方法更改文件和目录的名称。
如果这不是您想要的,请尝试
find ... -type ... -exec
下一节中的方法。– 不会。使用上述命令之一作为模板不会影响任何子目录中的文件/目录。如果你想这样做,你将不得不有目的地对方法进行相当多的调整。
例如,请参阅此答案中的第一个解决方案。
2.使用的通用解决方案
find ... -exec mv
下面的
find ... -exec mv
方法使您可以选择仅重命名文件或仅重命名目录-通过-type
标志。它也可以被调整以控制命令应该在子目录树中搜索文件或目录的深度——通过-maxdepth
标志。重命名前缀
以下命令替换
o l d prefix
为n e w prefix
,但 仅适用于目录。每个文件都可以在单独的子 shell 中重命名,但通过在内部有一个 for 循环(并用而不是-exec
关闭),命令运行效率更高:-exec
sh {} +
{} \;
如果您只想重命名文件,只需使用
-type f
而不是-type d
(容易记住:f
用于文件,d
用于目录)。重命名后缀
同样,这里是如何替换大量文件中的后缀:
解释
find .
在当前目录及其子目录中搜索。-maxdepth 1
不要在任何子目录中搜索。-type f
仅查找文件(排除目录)。-name "*d suffix"
仅搜索以 . 结尾的文件d suffix
。-exec sh -c '...'
在子 shell 中执行,允许命令替换,$(...)
.-exec sh -c 'for n; do mv ...' sh {} +
比做-exec sh -c 'mv ...' {} \;
同样事情的效率更高。 7{}
持有任何find
发现。echo
输出命令的结果——当你对结果满意时,删除
echo
并再次运行命令。mv "sou rce" "dest in"
执行实际的重命名,用新名称替换旧名称。
sou rce
dest in
%
请参阅POSIX shell 模式过滤。done
结束 for 循环。sh {} +
如前所述,sh {} +
关闭-exec sh -c
子句。重命名文件和目录
要一次性重命名文件和目录,只需省略
-type
:该
-maxdepth 1
子句确保子目录树中的任何文件/目录都不会受到影响。如果您故意要为所有 子目录中的所有文件重命名后缀,这里有一个示例:
一句警告。
此方法不适用于在一个命令中重命名许多不同子目录中的前缀。
3.使用Perl重命名的解决方案
本节专门针对那些 在您的系统上安装了由 Larry Wall 重命名的 Perl (或知道如何安装它)的人。 8
rename
我喜欢将Perl-script 重命名为的谨慎做法,prename
以避免将其与 Linux rename混淆。您无需担心是重命名前缀还是后缀,这一事实使 Perl 重命名易于使用。
例如,要替换
o l d prefix
为n e w prefix
,请执行以下操作:-n
标志产生预览的地方。一旦结果是您想要的,只需删除
-n
标志并再次运行命令。与第 1 节的 for-loop 方法一样,运行
prename
将重命名目录和文件。if -f
但是,您可以通过在重命名字符串的末尾 添加来选择仅重命名文件(不包括目录) ,如下所示: 9如果您只想重命名目录(排除文件),请使用
if !-f
:我发现 - 当使用正斜杠 (
/
) 作为分隔符时 - Perl rename 将仅重命名当前工作目录中的文件/目录,而不是任何子目录中的文件/目录。如果您使用其他字符作为分隔符,您实际上可以
prename
用来重命名子目录树中的文件/目录。这个答案的第二个解决方案是这种相当非正统的做法的一个例子。
更正常的做法是
find ... -execdir
与prename
.对于这样的示例,请参阅 此答案。
4.重命名文件或目录的其他好方法
如果您不喜欢上述任何方法,请考虑使用
sed
orawk
(可能与 结合使用xargs
)。参考
find ... -exec
是可选的,但更有效-exec
-n
预览结果prename
-f
, 以便只重命名常规文件(而不是目录)sed
awk
xargs
1在测试这个答案中提供的命令/解决方案时,我既没有使用过正版Linux,也没有使用正版Unix,而是Windows 10上的MSYS2,可以描述为在Microsoft Windows上运行的模拟arch-Linux。当然,对于像我这样的 Windows 用户来说,一个可行的替代方案是使用 Windows Subsystem for Linux (WSL)。
我使用 MSYS2 是因为我觉得它方便易用。
2如果有疑问,在考虑任何重命名之前,请检查
命令的结果
ls *\"*
和ls *\'*
.或者更好的是:
find . -name '*"*'
和find . -name "*'*"
。我认为,在文件/目录名称中使用引号肯定是自找麻烦。
此答案列出了文件/目录名称中禁止使用的字符。
– 对于 Linux/Unix,只有一个禁止字符:正斜杠 (
/
)。3我的目标不是一次性更改前缀和后缀的解决方案,如 Renaming files with Bash, remove prefix and suffix问题中所要求的那样。(如果您需要同时重命名前缀和后缀,我建议在一个命令中替换其中一个,然后在另一个命令中替换另一个。)
4我鼓励读者下载 zip 文件并将其解压缩到某个(空)目录,然后尝试我在此答案中提供的所有命令。
5对于包含空格的文件和目录,预览可能看起来不正确,因为它缺少周围的双引号 (
"
)。删除echo
仍然会使命令正确运行。(不要太从字面上理解预览!)
6我使用反斜杠 (
\
) 对长命令进行换行,这样读者就无需水平滚动。当您自己构建一个具体示例时,我建议删除反斜杠并将整个命令写在一行中。7要了解更多关于 和 之间的区别
{} +
,{} \;
请参阅例如 如何终止由-exec
(及其引用)调用的 shell 命令。8尝试在您的终端中 输入
rename
或(然后点击)。如果安装了 Perl rename,预计会看到 或类似的东西 - 其中包含该单词。 如果未安装,预计会看到类似 . 您可以尝试的另一件事是.prename
EnterUsage: rename [-v] [-n] [-f] perlexpr [filenames]
perlexpr
bash: prename: command not found
which prename
9 该评论说该
if -f
子句还将重命名符号链接。如果不重命名符号链接,它建议使用。
if (-f && ! -l)