【问题标题】:Rename multiple files by replacing a particular pattern in the filenames using a shell script [duplicate]通过使用 shell 脚本替换文件名中的特定模式来重命名多个文件 [重复]
【发布时间】:2011-07-27 06:38:51
【问题描述】:

编写一个可以自动重命名多个文件的简单脚本。例如,我们希望将文件 *001.jpg 重命名为用户定义的字符串 + 001.jpg(例如:MyVacation20110725_001.jpg) 此脚本的用途是让数码相机照片具有有意义的文件名。

我需要为此编写一个 shell 脚本。有人可以建议如何开始吗?

【问题讨论】:

标签: shell


【解决方案1】:

一个帮助你起步的例子。

for f in *.jpg; do mv "$f" "$(echo "$f" | sed s/IMG/VACATION/)"; done

在此示例中,我假设您的所有图像文件都包含字符串 IMG,并且您希望将 IMG 替换为 VACATION

shell 自动评估 *.jpg 到所有匹配的文件。

mv(文件的新名称)的第二个参数是sed 命令的输出,它将IMG 替换为VACATION

如果您的文件名包含空格,请注意"$f" 符号。您需要双引号来保留空格。

【讨论】:

  • 使用 bash,您还可以从字符串重定向:sed 's/foo/bar/' <<< "$f"
  • Susam 的优秀示例——这种用法也适用于我在 MingW 中将名为 *-1.0-SNAPSHOT.war 的文件更改为 *.war,如下所示:for i in *.war; do mv ${i} `echo ${i} | sed 's/-1.0-SNAPSHOT\.war/\.war/'`; done
  • 只是添加到这个..你也可以使用通配符,例如有一堆带有 IMGnnnn.jpg 的文件,其中 n 是一堆数字;那么你可以做类似 s/IMG.*/VACATION\\.jpg/
  • @MikeStewart 您链接到的 GNU 文档提供了许多非 POSIX 功能。有关参数扩展的 POSIX 规范,请参阅 POSIX.1-2008: § 2.6.2: Parameter Expansion。您链接到的另一个答案中的 ${file//IMG/myVacation} 替换不符合 POSIX。它不适用于dash。在 Debian 上,默认的 shdash。当dash 遇到${file//IMG/myVacation} 时,它会失败并出现Bad substitution 错误,因为此语法不符合POSIX。
  • @SusamPal 啊,是的,我知道 BASH 有许多不符合 POSIX 的功能。 (它在手册中说了很多)。但我很高兴您为该示例澄清并分享了一个更合适的链接。谢谢!
【解决方案2】:

您可以使用 rename 实用程序按模式重命名多个文件。例如,以下命令会将字符串 MyVacation2011_ 添加到所有具有 jpg 扩展名的文件中。

rename 's/^/MyVacation2011_/g' *.jpg

rename <pattern> <replacement> <file-list>

【讨论】:

  • 但是这个命令肯定有变种,rename就像我的RedHat 6.5上的mv
  • 这对我不起作用,因为我的文件太多:-bash: /usr/bin/rename: Argument list too long。但我同意如果你有一个较小的列表很好
  • @ixe013 这个重命名是 perl 版本,不是内置实用程序。按照stackoverflow.com/questions/22577767/… 的指南进行安装。
  • “参数列表太长”的问题可以通过使用find:find . -name *.jpg -exec rename &lt;pattern&gt; &lt;replacement&gt; {} \;来规避,这将对每个文件调用一次重命名。
  • @CpILL 它使用正则表达式捕获组,替换字符串将用匹配替换$&lt;groupNumber&gt;。例如rename 's/([^-]+)-([^.]+)/$2-$1/g' *。模式^([^-]+)-([^.]+) 意味着:从名称的开头,捕获1 个或多个不是- 的字符,然后期待一个破折号,然后捕获1 个或多个不是. 的字符。 $1 是第一个捕获,$2 是第二个。
【解决方案3】:

这个例子,我假设你所有的图片文件都以“IMG”开头并且你想用“VACATION”替换“IMG”

解决方法:先识别所有jpg文件,然后替换关键字

find . -name '*jpg' -exec bash -c 'echo mv $0 ${0/IMG/VACATION}' {} \; 

【讨论】:

  • 最佳答案,因为它允许遍历目录树,使用内置的 bash 实用程序并且易于配置。此外,该示例还提供了无损测试以确保更改正确。
  • 这里只是一个注释......非常明显但值得说明:'echo mv $0 ${0/IMG/VACATION}' 部分是将针对找到的每个文件运行的实际命令。所以,如果你把echo 留在那里,它只会回应它会做的事情。删除 echo 命令以实际移动文件,例如。 find . -name '*jpg' -exec bash -c 'mv $0 ${0/IMG/VACATION}' {} \;
  • 感谢 echo 让用户知道它是否会起作用
  • 最有用的;尽管您可能应该添加来自@dmmd 的注释。实际上,我将 echo 的输出转储到 shell 脚本进行检查,然后执行该脚本……因为我很偏执。
【解决方案4】:
for file in *.jpg ; do mv $file ${file//IMG/myVacation} ; done

再次假设您的所有图像文件都有字符串“IMG”,并且您想将“IMG”替换为“myVacation”。

使用 bash,您可以直接将字符串转换为 parameter expansion

示例:如果文件是 IMG_327.jpg,则mv 命令将像执行mv IMG_327.jpg myVacation_327.jpg 一样执行。这将针对在与*.jpg 匹配的目录中找到的每个文件完成。

IMG_001.jpg -> myVacation_001.jpg
IMG_002.jpg -> myVacation_002.jpg
IMG_1023.jpg -> myVacation_1023.jpg
等等……

【讨论】:

  • @MikeStewart 您链接到的 GNU 文档提供了许多非 POSIX 功能。有关参数扩展的 POSIX 规范,请参阅 POSIX.1-2008: § 2.6.2: Parameter Expansion。此答案中的 ${file//IMG/myVacation} 替换不符合 POSIX。它不适用于dash。在 Debian 上,默认的 shdash。当dash 遇到${file//IMG/myVacation} 时,它会失败并出现Bad substitution 错误,因为这种替换语法不符合POSIX。
【解决方案5】:
find . -type f | 
sed -n "s/\(.*\)factory\.py$/& \1service\.py/p" | 
xargs -p -n 2 mv

例如,将重命名 cwd 中名称以“factory.py”结尾的所有文件,以替换为以“service.py”结尾的名称

解释:

1) 在 sed cmd 中,-n 标志将抑制在应用 s/// 命令后将输入回显到输出的正常行为,如果替换,s/// 上的 p 选项将强制写入输出制作。因为 sub 只会在匹配时生成,所以 sed 只会输出以“factory.py”结尾的文件

2) 在 s/// 替换字符串中,我们使用 "&" 将整个匹配字符串插入到替换字符串中,后跟一个空格字符。因此,我们的 RE 匹配整个文件名至关重要。在空格字符之后,我们使用“\1service.py”插入我们在“factory.py”之前吞下的字符串,然后是“service.py”,替换它。因此,对于更复杂的转换,您必须将 args 更改为 s///(re 仍然匹配整个文件名)

示例输出:

foo_factory.py foo_service.py
bar_factory.py bar_service.py

3) 我们使用 xargs 和 -n 2 来一次使用 sed 2 个分隔字符串的输出,并将它们传递给 mv (我还把 -p 选项放在那里,这样你在运行它时会感到安全)。瞧。

【讨论】:

  • IMO 这是唯一有效的解决方案。美观、快速、灵活。
【解决方案6】:

另一种选择是:

for i in *001.jpg
do
  echo "mv $i yourstring${i#*001.jpg}"
done

正确删除echo

# 的参数替换将只保留最后一部分,因此您可以更改其名称。

【讨论】:

    【解决方案7】:

    你可以试试这个:

    for file in *.jpg;
    do
      mv $file $somestring_${file:((-7))}
    done
    

    您可以在man bash中看到“参数扩展”以更好地理解上述内容。

    【讨论】:

      【解决方案8】:

      无法评论 Susam Pal 的回答,但如果您要处理空格,我会用引号括起来:

      for f in *.jpg; do mv "$f" "`echo $f | sed s/\ /\-/g`"; done;
      

      【讨论】:

        猜你喜欢
        • 2021-11-30
        • 1970-01-01
        • 2016-03-14
        • 2013-05-02
        • 2018-06-09
        • 1970-01-01
        • 2021-01-21
        • 2014-01-06
        • 2016-10-08
        相关资源
        最近更新 更多