我有一个文件夹,里面有几个子文件夹,其中有一个在所有子文件夹中都同名的文件。例如:
abc/def_0/ghi.jpg
abc/def_5/ghi.jpg
abc/def_10/ghi.jpg
- ...
abc/pqr_0/ghi.jpg
abc/pqr_5/ghi.jpg
abc/pqr_10/ghi.jpg
我想将ghi.jpg
所有子文件夹中的此特定文件()重命名为:
abc/def_0/def_xyz_0.jpg
abc/def_5/def_xyz_5.jpg
abc/def_10/def_xyz_10.jpg
- ...
abc/pqr_0/pqr_xyz_0.jpg
abc/pqr_5/pqr_xyz_5.jpg
abc/pqr_10/pqr_xyz_10.jpg
我将非常感激任何帮助,因为我无法找到解决方案。谢谢!
答案1
您可以使用 Perl 重命名命令file-rename
为此。如果您不熟悉此工具,我建议您运行file-rename --version
以查看是否有它 - 任何非错误输出都表示您有。一些 Ubuntu 版本默认不附带它,因此您可能没有它,在这种情况下,您可以通过安装包来获取它rename
。(如果您没有它,“未找到命令”错误甚至可能会告诉您这一点。)
cd
到abc
包含要重命名文件的子目录的目录中并运行此命令。然后,如果它显示的重命名操作确实是您想要的,则再次运行它而无需-n
执行实际的重命名。
file-rename -n 's|^(.+)_(\d+)/ghi\.jpg$|$1_$2/$1_xyz_$2.jpg|' */ghi.jpg
这将使用 shell glob 生成要重命名的文件列表,并将其作为参数传递给要file-rename
重命名的文件。它假定您想要:
- 要重命名
ghi.jpg
位于目录的子目录中_
的文件(以 结尾,后跟数字)abc
。 - 每个文件的新名称为其包含的目录没有尾随下划线和数字,后跟
xyz
,后跟其包含目录名称的尾随下划线和数字。
其工作方式是,对文件进行操作,这些文件的路径作为参数传递给匹配s|pattern|substitution|
file-rename
pattern
(解释为正则表达式在Perl 方言)。它执行的操作是使用指定的substitution
. 名称不包含匹配项的文件pattern
不会被重命名。分隔符的选择并没有什么特别之处|
;我只是不想使用通常的分隔符,/
因为它出现在路径中。
在模式中^(.+)_(\d+)/ghi\.jpg$
:
^
匹配路径的开头和$
结尾。这只允许匹配传入的每个路径的整体,而不是其中的任何部分。(为了解决一个可能引起混淆的问题:传递的路径仍然是相对路径类似
def_0/ghi.jpg
,而不是类似 的绝对路径/home/you/abc/def_0/ghi.jpg
。当人们谈论“完整路径”时,他们通常指的是绝对路径。我说的“整个路径”只是指传入的每个完整参数,而不是其中较小的子字符串。)_
匹配其自身,即文字下划线字符。/
匹配其自身,即文字斜杠字符。(它不充当分隔符,因为我们改用了|
分隔符。)ghi
与文字文本匹配ghi
。jpg
与文字文本匹配jpg
。
替代$1_$2/$1_xyz_$2.jpg
意味着:
- 放置在第一个捕获组 ( ) 中的文本。这是与模式
$1
匹配的文本。.+
- 下划线,
_
。 - 放置在第二个捕获组 ( ) 中的文本。这是与模式
$2
匹配的文本。\d+
- 一道斜线,
/
。 - 再次是第一个捕获组(
$1
)。 - 文本
_xyz_
。 - 再次是第二个捕获组(
$2
)。 - 点,
.
。与模式不同,在替换中 a.
不会被特殊处理,因此不需要(也不应该)用 进行转义\
。 - 文本
jpg
。
有关使用的一般文档file-rename
,请参阅的输出file-rename --help
,man file-rename
, 和这篇博文。(我使用file-rename
而不是 命令rename
,因为在某些系统上rename
是另一个实用程序。在大多数系统中它们是相同的。)