批量重命名文件

25

我想批量重新命名目录中的一些文件,以便从文件名中去掉前面的数字和连字符。

Old file name: 2904495-XXX_01_xxxx_20130730235001_00000000.NEW
New file name:         XXX_01_xxxx_20130730235001_00000000.NEW

我该如何使用Linux命令完成这个任务?


可能是 Renaming files in bash 的重复问题。 - flx
9个回答

42

这应该使它变得更好:

rename 's/^[0-9]*-//;' *

它从文件名的开头获取连续出现的数字[0-9],然后加上连字符-并将其从文件名中删除。


如果你的机器上没有rename命令,你可以使用循环和mv来替代:

mv "$f" "${f#[0-9]*-}"

测试

$ ls
23-aa  hello aaa23-aa
$ rename 's/^[0-9]*-//;' *
$ ls
aa  hello aaa23-aa
或者:
$ ls
23-a  aa23-a  hello
$ for f in *;
> do
>   mv "$f" "${f#[0-9]*-}"
> done
$ ls
a  aa23-a  hello

2
这在我的 rename 版本上无法工作(util-linux-ng 2.17.2)。你使用的是哪个版本? - Yossarian
在 Fedora 和 Debian 发行版中,rename 命令位于 util-linux 软件包中,但似乎默认情况下不包含在 OSX 中。 - David Souther
@Yossarian,请检查我的更新答案,使用 mv 命令。这对你有用吗? - fedorqui
1
是的,mv 命令对我有效。看来 rename 必须有两个版本 - 我的需要三个参数(rename from to file)。 - Yossarian
@cjungel 不确定你的意思是什么。 - fedorqui

22

我认为如果你执行下面的命令,这个命令会更好:

ls * | sed -e 'p;s/old-name/new-name/' | xargs -n2 mv

这里

ls * - 列出当前文件夹中的所有文件
sed -e - 执行表达式
p; - 打印旧文件名
s/old-name/new-name/ - 生成新的文件名
xargs -n2 - 处理两个参数以使用mv命令
mv - 接收两个参数并执行移动操作

建议:在执行mv命令之前,使用echo验证您要达到的目标是否正确。

ls * | sed -e 'p;s/old-name/new-name/' | xargs -n2 echo

以下示例将

SCCF099_FG.gz5329223404623884757.tmp 重命名为
SCCF099_FG.gz

ls *tmp | sed -e 'p;s/\([0-9]\)\+\.tmp/ /g' | xargs -n2 echo
ls *tmp | sed -e 'p;s/\([0-9]\)\+\.tmp/ /g' | xargs -n2 mv

非常有帮助。谢谢! - Ryan
1
我知道这是旧的,但你能解释一下这行代码在做什么吗?这是我的理解:在调用sed时,如果有5个文件存在,表达式字符串会打印每一行,然后立即在其下方打印其查找和替换后的副本;然后,xargs将这个包含10个项目的列表现在2个一组进行解析,并将它们作为参数传递给mv。对吗? - Luke Davis
1
我对包含空格的文件名使用了稍微不同的命令:find . -print0 | sed -z -e 'p;s/old-name/new-name/' | xargs -n2 -0 mv - Peter Nowee

7
如果第一个数字始终具有相同的长度:
for F in *new ; do
    mv $F ${F:8}
done

${parameter:number} 进行的是子字符串扩展 - 从第8个字符开始取字符串。

在扩展中还有许多其他可用的字符串编辑方式来处理其他情况。


3

使用renamer(适用于Windows、Mac和Linux):

$ renamer --find '/\d+-(.*)/' --replace '$1' *

这将从当前目录中所有文件的开头删除所有数字和第一个连字符。


能否安装依赖项? - mindsupport
我不确定你的意思是什么...在renamer网站上有安装说明..这有帮助吗? - Lloyd
Node Package Manager似乎在包依赖方面出现问题,因此它没有安装一个命令,而npm也没有以自动模式安装依赖项。 - mindsupport
我刚刚运行了 npm install -g renamer 命令 - 它已经正确安装并且可以正常工作.. 请确保你已经安装了最新版本的 node.js.. 如果你仍然遇到问题,请在这里提出问题。 - Lloyd

2
这可能看起来有点复杂,但它非常有效,在*nix和OSX系统上都可以很好地工作。 它还是递归的,可以重命名当前目录以及任何子目录中的文件:
find . -regex '.*/[0-9]\{7\}[-].*' -print > temp1 && \
cp temp1 temp2 && \
vi -c ":g/\([0-9]\{7\}[-]\)\(.*\)/s//\2/" -c ":x" temp2 && \
paste temp1 temp2 > temp3 && \
vi -c ":g/^/s//mv /" -c ":x" temp3 && \
sh ./temp3 && \
rm temp1 temp2 temp3

以下是所发生情况的详细说明:

第一行指示找到(find)所有文件,以当前目录为起点(.),它们的名称匹配模式(-regex)为“7个数字,后跟一个破折号,后跟0个或多个字符”('.*/[0-9]\{7\}[-].*'),并将这些文件名和它们各自的路径写入名为temp1的文件中(> temp1)。请注意,-print指令在大多数情况下可能不是必需的,但它不会有任何问题。

find . -regex '.*/[0-9]\{7\}[-].*' -print > temp1 && \

接下来,将temp1的内容复制(cp)到一个名为temp2的文件中。

cp temp1 temp2 && \

接下来,使用vi文本编辑器打开temp2文件,并给vi两个命令(使用-c表示每个新命令):

  1. 命令#1:
    • 搜索temp2的每一行(:g),查找与上面相同的模式,但这次使用括号将结果分组(\([0-9]\{7\}[-]\)\(.*\))。
    • 对于每个匹配的行,将光标移动到找到匹配项的位置,并替换整个匹配项为匹配模式的第二组(\2)。
  2. 命令#2:
    • 保存对temp2所做的更改并关闭文件(:x)。

其结果如下:

 vi -c ":g/\([0-9]\{7\}[-]\)\(.*\)/s//\2/" -c ":x" temp2 && \

现在,将temp1中的行与temp2中的行拼接在一起(使用paste),并将每个新组合的行写入名为temp3的文件中(使用> temp3)。

paste temp1 temp2 > temp3 && \

接下来,再次运行 vi,执行与上述相同的步骤,但这次在文件 temp3 中搜索每行的开头(^),并在其后添加 mv 和一个空格(mv)。
vi -c ":g/^/s//mv /" -c ":x" temp3 && \

然后,执行temp3的内容(./temp3)作为shell脚本(sh)。

sh ./temp3 && \

最后,删除(rm)我们在整个过程中创建的每个临时文件。
rm temp1 temp2 temp3

1

1

vimv让你可以使用Vim的文本编辑功能重命名多个文件。

输入vimv会打开一个Vim窗口,其中列出了所有文件,您可以进行模式匹配、可视化选择等操作以编辑名称。在退出Vim后,文件将被重命名。

README文件中的{{screencast}}演示了它是如何解决原作者的问题的。

[免责声明:我是这个工具的作者]


0
你可以使用这个工具:rnm 实现你想要的代码:
rnm /path/to/the/directory -fo -dp -1 -rs '/^\d+-//' -ss '^\d+-'

-fo 是文件模式
-dp 是目录深度(-1 表示无限深度)。
-rs 是替换字符串。 \d+- 正则表达式将被替换为空字符串。
-ss 是搜索字符串,它搜索带有 ^\d+- 正则表达式的文件。(虽然可以省略,但屏幕上会打印一些无害的错误消息)。


0

我真的很喜欢像“rename *.mp3 *.mp4”这样的东西。

但是其他答案都没有给我这个。所以我写了一个Haskell程序来实现它。

https://hackage.haskell.org/package/batch-rename

使用这个命令,你可以做到: batch_rename "DCIM*.jpg" "*.png"


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