使用shell脚本批量重命名

我有一个名为的文件的文件夹

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 

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

这是因为bash用空格分隔元素,所以你要命令它把' input '移动到' (1) '。

解决这个问题的方法是通过使用IFS变量的新行来告诉bash分裂。

喜欢这个:

  IFS = $ '\ n' 

然后做你的命令。

不过,我建议你使用find来执行此操作,而不是使用-exec命令。

例如:

 找到* .txt -exec mv “{}” `echo “{}” |  sed -e's /input \(\([0-9] * \))\ txt / input_ \ 1.in /'` \; 

注意:我从内存中写入这个,我测试了这个,所以让我们尝试调整它。

希望这可以帮助。

你忘了引用你的论点。

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

不需要调用外部命令

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

你已经修好了,你需要引用$f参数给mv

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

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

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