我发现了很多有关如何使用命令行重命名多个文件的问题。但是我无法解决重命名此文件名的具体问题:
something_4M_something_something_manyothersomethings.csv
进入这个:
something_4_M_something_something_manyothersomethings.csv
我需要的是将字段拆分4M
为4_M
但我无法做到这一点(注意:每个某物用下划线分隔,还有很多其他字段,我相信这对于任务来说并不重要)。
我所做的是以下内容,但它不起作用,正如我所期望的那样,我认为这是正则表达式的问题,但我无法找出更好的方法:
rename -n 's/.4M/$&_4_M/' *
另外,我不知道我写的东西到底是如何工作的,因为我在与此类似的问题之一的评论中发现了类似的内容,但我再也找不到它了。
答案1
如果您真正想做的只是替换4M
为4_M
,那么您的正则表达式的变体可以执行以下操作:
$ ls
something_4M_something_something_manyothersomethings.csv
$ rename -n 's/4M/4_M/' *
'something_4M_something_something_manyothersomethings.csv' would be renamed to 'something_4_M_something_something_manyothersomethings.csv'
正则表达式适用于任何东西里面名称,因此您不需要执行特定操作来保留领先的“某物”。
如果您想做其他事情,例如将第一个“某事”移至第二个“某事”,或限制为4M
下划线后第一次出现,请编辑您的问题并澄清。
正如评论中所观察到的,-n
进行了一次空运行,因此它显示了会发生什么,并且实际上并不执行操作。
由于问题中的示例已经使用了-n
,我假设提问者可以理解这一点。
答案2
使用 Raku(以前称为 Perl_6)
对于单个文件:
~$ raku -e ' \
my $name = dir(test => /^ something_4M_somethingelse \. csv $/)[0]; \
my $modname = S/^ something_<(4M)>_somethingelse \. csv $/4_M/.IO given $name; \
($name,$modname).say; \
#rename($name,$modname, createonly => True);'
对于多个文件:
~$ raku -e ' \
my @names = dir(test => /^ something_<digit><upper>_somethingelse \. csv $/); \
my @modnames = do for @names {S/^ something_<(<digit><upper>)>_somethingelse \. csv $/$<digit>_$<upper>/.IO given $_;}; \
for [Z] @names,@modnames -> ($x,$y) { ($x,$y).say }; \
#for [Z] @names,@modnames -> ($x,$y) { rename($x,$y, createonly => True) };'
目录输入:
~$ ls
something_4M_somethingelse.csv something_5N_somethingelse.csv something_6O_somethingelse.csv
目录输出(多文件重命名):
~$ ls
something_4_M_somethingelse.csv something_5_N_somethingelse.csv something_6_O_somethingelse.csv
警告:先备份!!
简要说明(单文件重命名):dir()
使用正则表达式匹配(“副词”)选项获取感兴趣的文件的列表test => / ... /
,并且仅采用一个元素(无论如何[0]
),将其存储在标量变量中$name
。检查该变量表明它是一个.IO
对象。
使用熟悉的S///
习惯用法修改given $name
变量,并将修改后的名称存储为$modname
.请注意,这里,S///
字符串化 so.IO
方法调用被添加到S///
so that也是$modname
一个.IO
对象。
在正则表达式中,不熟悉的符号可能是<(…)>
表示法。但这只是Raku的捕获标记,因此虽然 的左半部分的整个匹配项S///
被识别,但仅捕获4M
其中的匹配项<(…)>
,并在 的右半部分进行修改S///
。
.IO
如果获得了所需的起始/结束对象,该行($name,$modname).say;
应生成类似于以下内容的输出:
("something_4M_somethingelse.csv".IO "something_4_M_somethingelse.csv".IO)
一旦一切看起来都不错,您可以取消 Raku 代码最后rename()
一行的注释,以实际将倒数第二行中列出的文件重命名为.say
.
注意:在上面的代码createonly => True
中包含副词/选项rename()
意味着rename()
不会破坏现有的文件名(较短的形式:createonly
具有相同的作用)。删除createonly => True
或:createonly
副词/选项以获得默认值(False
即破坏)并允许重命名(覆盖)预先存在的文件/文件名。
https://docs.raku.org/syntax/S$SOLIDUS$SOLIDUS$SOLIDUS
https://docs.raku.org/routine/rename
https://raku.org