![使用正则表达式重命名文件](https://linux22.com/image/201871/%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E9%87%8D%E5%91%BD%E5%90%8D%E6%96%87%E4%BB%B6.png)
我的 Linux 计算机上的一个文件夹中有许多文件,其名称如下:
11, 12, 13, 14, 15, 21, 22, 23, 24, 25, 31, 32, 33, 34, 35
我想使用正则表达式以 .inp 扩展名重命名
我试过
mv * *.inp
mv: target '*.inp' is not a directory
这提供了一个错误。我还尝试使用正则表达式 [123][12345] 而不是 *.
所以,我明白 mv 是用来移动文件的。我还想到也许我可以用来./*.inp
强制 mv 在同一个文件夹中写入,但它失败了。那么,除了不正确理解如何mv
工作之外,我将如何继续完成这项工作mv
?
答案1
您的命令的问题在于,该mv
命令只能移动/重命名单个文件(当恰好给出两个命令行参数时),或将一堆文件移动到单个目标目录(超过两个命令行参数)。
在您的情况下,您使用 的扩展* *.inp
作为参数,这将扩展为当前目录中的所有可见文件名,后跟匹配的名称*.inp
。假设这扩展到两个以上的名称,那么最后一个参数必须是目录的名称,该命令才能成为有效mv
命令,否则您将收到“不是目录”错误。
在这种情况下,我们希望mv
一次使用两个参数,为此我们需要使用 shell 循环:
for name in [123][1-5]; do
mv "$name" "$name.inp"
done
这将循环遍历与您提到的文件名通配模式(变体)匹配的所有名称(注意,这不是正则表达式)。在循环体中,当前名称将存储在变量中name
,并且只需在名称末尾mv
添加即可重命名文件。.inp
这不会阻止mv
在可能存在名称冲突的情况下覆盖现有文件。为此,假设您使用 GNU mv
,您可能需要mv
与其--no-clobber
(或-n
) 选项一起使用,或者可能与其--backup
(或-b
) 选项一起使用。
或者,您可以显式检查目标名称是否存在,并跳过当前文件(如果存在)(如果碰巧有一个与目标名称同名的目录,这也可以避免将文件移动到现有目录中):
for name in [123][1-5]; do
[ -e "$name.inp" ] || [ -L "$name.inp" ] && continue
mv "$name" "$name.inp"
done
将 GNUmv
与--no-target-directory
(或) 与或-T
结合使用可以避免覆盖现有文件(或使用 备份它们),并且还可以避免将文件移动到恰好与目标名称同名的子目录中。-n
-b
-b
答案2
您可以使用perl-rename
工具:
rename -n 's/$/.inp/' [0-9][0-9]
(或者,使用'$_ .= ".inp"'
追加.inp
,应该更快,因为不需要评估正则表达式。)
-n
如果您对输出满意,请删除。
答案3
Withzsh
的批量重命名zmv
功能:
autoload -Uz zmv
zmv '[1-3][1-5]' '$f.inp'
相对于此处提到的其他一些解决方案的优势:
- 它会首先运行一些健全性检查。例如,如果这可能导致任何数据丢失,它会在执行之前中止命令任何重命名。
[1-5]
[12345]
与中相同zsh
。在bash
最常见的语言环境和 GNU 系统中,[1-5]
更像是[12345١٢٣٤۱۲۳۴߁߂߃߄१२३४১২৩৪੧੨੩੪૧૨૩૪୧୨୩୪௧௨௩௪౧౨౩౪౹౺౻౼౽౾೧೨೩೪൧൨൩൪෧෨෩෪๑๒๓๔໑໒໓໔༡༢༣༤༪༫༬༭၁၂၃၄႑႒႓႔፩፪፫፬១២៣៤៱៲៳៴᠑᠒᠓᠔᥇᥈᥉᥊᧑᧒᧓᧔᧚᪁᪂᪃᪄᪑᪒᪓᪔᭑᭒᭓᭔᮱᮲᮳᮴᱁᱂᱃᱄᱑᱒᱓᱔⁴₁₂₃₄⅐⅑⅒⅓⅔⅕⅖⅗⅘⅙⅛⅜⅟①②③④⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳⑴⑵⑶⑷⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴⓵⓶⓷⓸⓾❶❷❸❹❿➀➁➂➃➉➊➋➌➍➓〡〢〣〤㉈㉉㉊㉋㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㋀㋁㋂㋃㋉㋊㋋㍙㍚㍛㍜㍢㍣㍤㍥㍦㍧㍨㍩㍪㍫㍬㍭㍮㍯㍰㏠㏡㏢㏣㏩㏪㏫㏬㏭㏮㏯㏰㏱㏲㏳㏴㏵㏶㏷㏸㏹㏺㏻㏼㏽㏾꘡꘢꘣꘤꣑꣒꣓꣔꤁꤂꤃꤄꧑꧒꧓꧔꧱꧲꧳꧴꩑꩒꩓꩔꯱꯲꯳꯴1234
答案4
如果您的发行版可用,请使用 mmv 命令。
参见示例http://manpages.ubuntu.com/manpages/bionic/man1/mmv.1.html