代码之家  ›  专栏  ›  技术社区  ›  Aakash Goel

使用shell脚本进行批重命名

  •  3
  • Aakash Goel  · 技术社区  · 15 年前

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

    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 回复  |  直到 14 年前
        1
  •  3
  •   NawaMan    15 年前

    那是因为巴什 for 用空格“”拆分元素,以便命令它移动“ input “to” (1) '.

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

    这样地:

    IFS=$'\n'

    然后执行你的命令。

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

    例如:

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

    注意:我是从记忆中写的,我做了测试,所以让我们试着调整它。

    希望这有帮助。

        2
  •  3
  •   Ignacio Vazquez-Abrams    15 年前

    你忘了引用你的论点。

    ... mv "$f" "$(echo "$f" | ... )" ; done
    
        3
  •  3
  •   ghostdog74    15 年前

    无需调用外部命令

    #!/bin/bash
    shopt -s nullglob
    shopt -s extglob
    for file in *.txt
    do
      newfile="${file//[)]/}"
      newfile="${file// [(]/_}"
      mv "$file" "${newfile%.txt}.in"
    done
    
        4
  •  1
  •   Brian Campbell Dennis Williamson    14 年前

    既然你已经修好了,你需要引用 $f 论证 mv .

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

        5
  •  0
  •   Omar Ali    15 年前
    for f in *.txt ; do mv "$f" `echo $f | sed -e 's/input\ (\(\d*\))\.txt/input_\1.in/'` ; done
    
        6
  •  0
  •   Ole Tange    15 年前

    如果你有GNU并行 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