在文件夹中批量重命名文件的Shell/Bash快捷方式

85

有没有在Shell/Bash中可以根据正则表达式或其他标准来重命名文件夹中所有文件的快捷方式。我想要的是,在我的文档文件夹中,有一个命名约定为以下的100个文本文件:

<longdocumentidentifier>-doc-<counter>.txt.

我需要将所有文件按照上述规则重命名为:

doc-<counter>.txt

有没有一个一行代码的解决方案可以帮我解决上述问题?

8个回答

154

我建议做类似于这样的事情:

for i in *-doc-*.txt; do mv "$i" "${i/*-doc-/doc-}"; done

${i/*-doc-/doc-}将第一个出现的*-doc-替换为doc-

如果你需要执行多个替换(参见评论1),你需要使用${var//Pattern/Replacement}变体。如果你需要替换名称开头,你需要使用${var/#Pattern/Replacement},如果你需要替换结尾(即扩展名),你需要使用${var/%Pattern/Replacement}形式。

更多细节请参见Shell Parameter Expansion(Shell参数扩展)。这种扩展仅适用于bash。


2
这对于一个稍微不同的情况非常有帮助;我想用破折号替换一些文件名中的所有空格:for i in *; do mv "$i" ${i//\ /-}; done。请注意,为了使其工作,我必须引用原始文件名。 - Richard Turner
我用它来删除所有脚本名称中的 .sh 后缀 :-) for i in *.sh; do mv $i ${i/.sh/}; done - m3nda
1
@erm3nda 注意:${i/.sh/}会删除第一个匹配的.sh字符串。为确保您删除扩展名(我假设您想要这样做),您应该使用${i/%.sh/} - Sorin
因为使用 * 来匹配被 i/ 替换的元素,所以我没有猜到 % 的工作原理类似于正则表达式中的 $1 匹配组。非常好,谢谢。 - m3nda
@erm3nda%与$1无关。/%表示匹配字符串的后缀。 - Sorin
当你使用/(.*).sh/$1/时,$1是正则表达式中的一个占位符,可以帮助你节省一些代码。我只是评论了如何比较两种情况。我没有想到参数替换会使用其他字符来完成它的工作。抱歉 :-) 谢谢。 - m3nda

28
如果您有rename命令,那么rename 's/^.*-doc-/doc-/' *.txt应该可以解决问题。

16

有一个prename,允许您使用正则表达式:

prename 's/^.*-doc-(.*\.txt)$/doc-$1/'  *.txt

使用选项 -n 进行模拟:

prename -n 's/^.*-doc-(.*\.txt)$/doc-$1/'  *.txt

注意:在许多Linux发行版中,该实用程序被称为rename。但并非所有Linux发行版都是这样的 - 因此,我使用与Perl附带的实用程序相同的规范名称。


12

如果您想递归地处理子目录,也可以使用以下方法:

find . -maxdepth N -type f -name "$pattern" | sed -e 'p' -E -e "s/$str1/$str2/g" | xargs -n2 mv
在自动支持扩展正则表达式的系统中,您可以省略-E
优点:
- 递归进入子目录 - 您可以控制递归的最大深度 - 您可以重命名文件和/或目录(-type f | d)
缺点:
- 正则表达式稍微复杂一些,因为您必须剥离路径以获得文件名
(答案修改自这里

当我运行这个程序时,出现了以下错误:sed: -e expression #2, char 33: unterminated \s' command`。有什么建议吗? - Peter

8

大多数Linux系统内置了重命名命令,例如,可以轻松完成此操作。

个人而言,我也更喜欢使用正则表达式,这就是为什么我已经携带着这个脚本很长时间了(阅读:自上世纪80年代末或90年代初以来):

#!/usr/bin/perl

($op = shift) || die "Usage: $0 expr [files]]\n";

if(!@ARGV)
  {
  @ARGV = <STDIN>;
  chop(@ARGV);
  }

for (@ARGV)
  {
  $was = $_;
  eval $op;
  die $@ if $@;

  if ($was ne $_)
    {
    print "rename($was,$_)\n";
    rename($was,$_);
    }
  }

当安装完成后,您可以执行以下操作:

script-name 's/.*-doc(.*).txt/doc$1.txt/' *.txt

6
mmv "*-doc-*" "doc-#2"

mmv命令代表“批量移动(mass move)”


3
如果你不介意使用外部工具,这里有一个:rnm官方网站
对于你的特定问题,命令应该是:
rnm -rs '/.*-doc-/doc-/' *.txt

或者

rnm -rs '/.*-(doc-.*\.txt)/\1/' *.txt

你可以在这里找到更多相关的示例和文档。


0
找到所有以“*scss”结尾的文件,使用xargs命令逐行处理每个文件,并将其重命名为以“.scss”结尾的文件(即删除“.css”部分)。
例如,如果您有一堆以“.css.scss”结尾的文件,并且想要将它们重命名为以“.scss”结尾的文件,则可以调整正则表达式和find参数以满足您的需求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接