使用 shell 脚本批量重命名

Posted

技术标签:

【中文标题】使用 shell 脚本批量重命名【英文标题】:Batch renaming using shell script 【发布时间】:2011-04-02 05:08:27 【问题描述】:

我有一个文件夹,其中的文件名为

input (1).txt
input (2).txt
input (3).txt
...
input (207).txt

如何将它们重命名为

input_1.in
input_2.in
input_3.in
...
input_207.in

我正在尝试这个

for f in *.txt ; do mv $f `echo $f | sed -e 's/input\ (\(\d*\))\.txt/input_\1.in/'` ; done

但它给了我

mv: target `(100).txt' is not a directory
mv: target `(101).txt' is not a directory
mv: target `(102).txt' is not a directory
...

我哪里做错了?


我现在已经加了引号,但我现在明白了

mv: `input (90).txt' and `input (90).txt' are the same file

它以某种方式试图将文件重命名为相同的名称。这是怎么回事?

【问题讨论】:

【参考方案1】:

正如您已经修复的那样,您需要将 $f 参数引用到 mv

关于你的第二个问题,sed 不支持\d。你可以改用[0-9]

【讨论】:

【参考方案2】:

如果您安装了 GNU Parallel http://www.gnu.org/software/parallel/,您可以这样做:

seq 1 207 | parallel -q mv 'input ().txt' input_.in

观看 GNU Parallel 的介绍视频以了解更多信息: http://www.youtube.com/watch?v=OpaiGYxkSuQ

【讨论】:

【参考方案3】:
for f in *.txt ; do mv "$f" `echo $f | sed -e 's/input\ (\(\d*\))\.txt/input_\1.in/'` ; done

【讨论】:

【参考方案4】:

无需调用外部命令

#!/bin/bash
shopt -s nullglob
shopt -s extglob
for file in *.txt
do
  newfile="$file//[)]/"
  newfile="$file// [(]/_"
  mv "$file" "$newfile%.txt.in"
done

【讨论】:

【参考方案5】:

那是因为 bash for 用空格' ' 分割元素,所以你命令它将'input' 移动到'(1)'。

解决这个问题的方法是告诉 bash 使用 IFS 变量换行。

像这样:

IFS=$'\n'

然后执行你的命令。

不过,我建议您使用find 来代替-exec 命令。

例如:

find *.txt -exec mv "" `echo "" | sed -e 's/input\ (\([0-9]*\))\.txt/input_\1.in/'` \;

注意:我是凭记忆写的,我确实对此进行了测试,所以让我们尝试调整一下。

希望这会有所帮助。

【讨论】:

还是这个mv: 'input (90).txt' and 'input (90).txt' are the same file 我不认为你可以使用 '\d'(我记得),尝试使用 '[0-9]'。 @Lazer: 在sed 转义\d 引入了十进制字符表示\d97 == "a"【参考方案6】:

你忘记引用你的论点了。

... mv "$f" "$(echo "$f" | ... )" ; done

【讨论】:

以上是关于使用 shell 脚本批量重命名的主要内容,如果未能解决你的问题,请参考以下文章

sh 在Shell中批量重命名

for in循环语句批量重命名的问题;bash

用shell命令对文件重命名

linux下怎么批量重命名这些文件

sh [LUA] Redis批量/批量操作脚本(重命名,删除)

使用 bash 脚本批量重命名 FTP 服务器上的文件