我有一堆文件想要重命名。它们的文件名采用特定格式:
p1.uniquenameA#blah_a
p2.uniquenameB#blah_b
p3.uniquenameC#blah_c
p4.uniquenameD#blah_d
p5.uniquenameE#blah_e
p6.uniquenameF#blah_f
p7.uniquenameG#blah_g
p8.uniquenameH#blah_h
p9.uniquenameI#blah_i
p10.uniquenameJ#blah_j
每个唯一的文件名之前都有一个前缀。在这种情况下,该前缀以字母开头p
,后面有一个数字,p
该数字递增一。句点 ( .
) 将前缀与唯一文件名分隔开。每个唯一文件名后面都有一个以主题标签 ( #
) 开头的后缀。我想删除从句点开始的前缀(包括句点),我还想删除从主题标签开始(包括主题标签)的后缀。我希望生成的文件名只是句点和哈希标签之间的唯一文件名,如下所示:
uniquenameA
uniquenameB
uniquenameC
uniquenameD
uniquenameE
uniquenameF
uniquenameG
uniquenameH
uniquenameI
uniquenameJ
我是脚本编写新手,因此如果您除了提供代码之外还能解释代码的工作原理,我将不胜感激。
答案1
如果您拥有perl
的版本rename
(有时称为prename
),您可以应用正则表达式替换:
rename -n 's/^.*?\.(.*?)#.*/$1/' *
如果您不了解正则表达式 (RE),它们非常值得学习。
s/xx/yy/
- 用。。。来xx
代替yy
^
- 匹配隐式行首.*?
- 匹配尽可能短的字符串任何内容的零个或多个字符以模式匹配的其余部分为准\.
- 匹配文字点.
(该.
字符代表任何事物,但是\.
是一个字面点)(
...)
匹配括号内的模式并为其指定匹配编号 1..9;后来被引用$1
(第二个(
......)
将是$2
,等等)#
- 文字字符.*
- 最长的比赛是任何内容的零个或多个字符(这.
是任何事物且*
前一项的意思是_零个或多个)
-n
当您高兴时删除(“无操作”)会工作。将其替换为-v
以查看实际发生的情况,或者忽略它以进行静默操作。
答案2
这是awk
执行该任务的脚本:
仅用于打印/调试:
awk 'match($0,/(^[^\\.]+.)([^#]+)/,m){print "mv "$0" "m[2] }' input.txt
进行重命名:
awk 'match($0,/(^[^\\.]+.)([^#]+)/,m){system("mv "$0" "m[2])}' input.txt
输入.txt
p1.uniquenameA#blah_a
p2.uniquenameB#blah_b
p3.uniquenameC#blah_c
p4.uniquenameD#blah_d
p5.uniquenameE#blah_e
p6.uniquenameF#blah_f
p7.uniquenameG#blah_g
p8.uniquenameH#blah_h
p9.uniquenameI#blah_i
p10.uniquenameJ#blah_j
输出
mv p1.uniquenameA#blah_a uniquenameA
mv p2.uniquenameB#blah_b uniquenameB
mv p3.uniquenameC#blah_c uniquenameC
mv p4.uniquenameD#blah_d uniquenameD
mv p5.uniquenameE#blah_e uniquenameE
mv p6.uniquenameF#blah_f uniquenameF
mv p7.uniquenameG#blah_g uniquenameG
mv p8.uniquenameH#blah_h uniquenameH
mv p9.uniquenameI#blah_i uniquenameI
mv p10.uniquenameJ#blah_j uniquenameJ
答案3
这是一个使用的解决方案sed
for i in *
do
mv $i $( echo $i | sed 's/p[[:digit:]]*\.\([^#]*\)\#.*/\1/' )
done
目标是sed
通过查找p
后跟任意数量的数字和句点来创建的。从该时期开始到该角色的角色#
是记住了到寄存器中,整个文件名被替换为记住了人物。