使用正则表达式重命名文件

使用正则表达式重命名文件

我的 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

相关内容