使用shell脚本批量重命名

时间:2010-08-22 06:47:40

标签: bash unix shell rename

我有一个名为

的文件夹
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

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

6 个答案:

答案 0 :(得分:3)

你忘了引用你的论点。

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

答案 1 :(得分:3)

这是因为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/'` \;

注意:我是从内存中写的,我测试了这个,所以试试吧。

希望这有帮助。

答案 2 :(得分:3)

无需调用外部命令

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

如果你安装了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