【问题标题】:How to rename files in bash script如何在 bash 脚本中重命名文件
【发布时间】:2014-10-08 03:55:58
【问题描述】:

我在 /media/user/docs 下有一组文件夹 (>=50),具有以下命名约定:

[2001] xxx 1
[2002] yyy
zzz

我想编写一个 bash 脚本将这些文件夹重命名为这种格式:

xxx 1 (2001)
yyy (2002)
zzz

如何通过使用 rename 或任何其他 Linux 命令来实现?我的工作环境是 Ubuntu 14.04。谢谢。

【问题讨论】:

  • 他们有扩展吗?
  • 抱歉,这些是文件夹,不是文件
  • 你知道有这方面的工具,使用命令行结帐mmv 和我的答案,使用GUI 看看easytag

标签: bash rename mv


【解决方案1】:

给定一个包含此内容的文件:

$ cat a
[2001] xxx
[2002] yyy
zzz

这通过使用反向引用(并转义 [])以您想要的方式替换它:

$ sed 's/\[\([0-9]*\)\] \(\w*\)$/\2 (\1)/' a
xxx (2001)
yyy (2002)
zzz

这样你就可以完全一样地使用rename

rename 's/\[\([0-9]*\)\] \(\w*\)$/\2 (\1)/' *
            ^^^^^^^^^^   ^^^^^^^  ^^^^^^^
               |            |     print them back
        catch numbers      catch words

【讨论】:

  • 如果要拼接的目录超过50个文件夹(cat),此方案不可行
  • Carefule, rename 可能是三个或四个不同程序之一,请参阅:mywiki.wooledge.org/BashFAQ/030#Nonstandard_tools
  • @ÉdouardLopez 并因此投反对票?嗯。好吧,它在我的计算机上运行得很好,据说在 OP 中也运行良好(尽管我猜他得到了太多文件错误)。不过,很高兴知道存在多个 rename 工具。
  • 意识到不可移植性,您唯一的答案是“它适用于我和 OP”?在您的答案中添加警告会更好
  • @ÉdouardLopez 再次阅读我的评论,您会发现我不知道存在多个重命名工具。更新以表明它,因为你是对的,最好在已知时表明它。
【解决方案2】:

mv

$ ls -d [*
[2001] yyy 2    [2002] xxx 1

做:

for i in [*; do
      new=$(echo $i | tr "[|]" "(|)" | awk '{for (i=2;i<=NF;i++) printf $i" "; print $1}');
      mv "$i" "$new"; 
done

$ ls -d *\)
xxx 1 (2002)    yyy 2 (2001)

它将[] 替换为()tr,然后为每个以[ 开头的文件切换具有awk 的列。

希望对你有帮助


如果是文件,而不是文件夹:

如果您有超过 1 个空格和扩展名:

for i in [*.ext; do
      new=$(echo ${i%.*} | tr "[|]" "(|)" | awk '{for (i=2;i<=NF;i++) printf $i" "; print $1}');
      mv "$i" "$new.ext"; 
done

它将文件名[2002] yyy 1.ext 转换为yyy 1 (2002).ext

【讨论】:

  • 如果文件夹名称为“[2001] test 2”,则将其重命名为“test(2001)”不正确。
  • @justinw 是的,你是对的,但它不在你的例子中,我猜不出来,编辑你的问题并详细说明文件名的样子。
【解决方案3】:

无论有没有文件扩展名都可以:

#!/bin/bash

[[ BASH_VERSINFO -ge 4 ]] || exit 1  ## Let's make minimum Bash version to 4.0.

shopt -s nullglob

for F in "$PREFIX"*; do
    read A B <<< "${F##*/}"
    [[ $A == \[*\] && -n $B && -d $F ]] || continue
    A=${A:1:${#A} - 2}
    X=''
    if [[ $B =~ (.[^. ]+)+$ ]]; then
        X=$BASH_REMATCH
        B=${B:0:${#B} - ${#X}}
    fi
    echo mv -- "$F" "${PREFIX}${B} ($A)$X"
done

试运行后删除echo

这是测试的结果:

mv -- /var/tmp/test/[2001] A /var/tmp/test/A (2001)
mv -- /var/tmp/test/[2001] B.txt /var/tmp/test/B (2001).txt
mv -- /var/tmp/test/[2001] C.txt.gz /var/tmp/test/C (2001).txt.gz

-d $F 确保只处理目录。如果您想要定位文件,请更改为 -f $F,或者如果两者都需要,则只需删除表达式。

【讨论】:

  • 不需要$ 登录[[ ]] :)
【解决方案4】:

超级简单的解决方案

使用mmv package

mmv -r '\[*\]\ *' '#2 (#1)'

详情

这有点复杂,因为您需要转义方括号,这里是short explanation

注意-r 是重命名目录所必需的。

之前

ls -1 ./
  [2001] xxx
  [2002] yyy
  zzz

之后

ls -1 ./
  xxx (2001)
  yyy (2002)
  zzz

【讨论】:

  • 这个包看起来很有用,谢谢推荐。我会试一试的。
猜你喜欢
  • 2014-07-17
  • 2016-05-12
  • 2015-08-02
  • 2013-06-10
  • 2016-04-30
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 2010-12-29
相关资源
最近更新 更多