我有大量的文件要重命名,数字越来越多,似乎没有重命名功能

时间:2014-09-16 15:33:46

标签: file sed renaming

我一直在好好挖掘并发现"重命名"我不是很熟悉计算机,但我已经找到了我所发现的东西。 到目前为止 - 我能够使用sed找到我想要搜索的内容,但我无法找到如何替换我实际需要的内容(希望这是有意义的)。

所以 - 场景: 我有3个批次(2000,2000和1000)的5000个文件,生成它们的程序总是从1到x的数字,所以time_step_1 ...... 我需要文件是连续的(所以不是从1开始的批次)

我试过了: ls time_step_*|sed 's/[0-9]\(.*\)/mv & time_step_\1+2001/' 并打印出来:

time_step_mv 10.txt time_step_0.txt+2001
time_step_mv 11.txt time_step_1.txt+2001
time_step_mv 12.txt time_step_2.txt+2001
time_step_mv 13.txt time_step_3.txt+2001
time_step_mv 14.txt time_step_4.txt+2001
time_step_mv 15.txt time_step_5.txt+2001
time_step_mv 1.txt time_step_.txt+2001
time_step_mv 2.txt time_step_.txt+2001
time_step_mv 3.txt time_step_.txt+2001
time_step_mv 4.txt time_step_.txt+2001
time_step_mv 5.txt time_step_.txt+2001
time_step_mv 6.txt time_step_.txt+2001
time_step_mv 7.txt time_step_.txt+2001
time_step_mv 8.txt time_step_.txt+2001
time_step_mv 9.txt time_step_.txt+2001

但文件名本身并没有改变 我已经管理了相同的输出几次。

我想我了解管道和节省"人物等等,但就像我说的那样,不是很熟悉计算机,也不像我在读过的各种帖子上的术语感到困惑。

非常感谢所有人的帮助

2 个答案:

答案 0 :(得分:1)

这适用于第二批,然后为第三批

执行+3000
for f in time_step_*; do 
   n=${f%.*}; n=${n##*_}; ((n+=2000));
   mv "$f" time_step_$n.txt
done

答案 1 :(得分:1)

因此...

首先,让我指出您在Bash wiki的ParsingLS页面。它强调了信任ls命令输出的危险。这并不是说你不应该这样做,但如果你意识到危险,你应该只做。 :)

一些基本的东西:

  • sed不是一种编程语言,它不知道如何做数学。
  • 您在正则表达式中匹配的任何内容都需要在输出中进行说明,甚至是表达式开头和结尾处的“隐含”内容。这就是您在输出字符串中嵌入mv的原因。

你说:

 ls time_step_* | sed 's/[0-9]\(.*\)/mv & time_step_\1+2001/'

这样可以获取time_step_12.txt这样的文件名,并用替换字符串替换 12.txt 。尽管sed不能进行数学运算,但你真正想要在这里使用的正则表达式已经考虑了整组输入文本。例如,在bash中:

 ls time_step_* | sed -r 's/^(.*_)([0-9]+)(.*)/mv & \1\2\3/'

结果是一组命令,你可以通过将| sh添加到行的末尾来管道sh(或bash),一旦你验证它们是正确的,就执行命令。请注意-r选项,它在许多实现中告诉sed将正则表达式解释为ERE而不是BRE。如果这对你不起作用(因为你使用的是旧的unix,SVR4等),请说明,我们可以将正则表达式转换为BRE。

我会指出这不是一个解决这个问题的好方法,最值得注意的是,正如我所说,sed不做数学。如果要将整数添加到文件名的组件中,则需要使用能够进行数学运算的内容来处理它。喜欢bash。

您可以使用sed提取部分数据,然后在简单的while循环中处理它:

for file in time_step_*.txt; do
  number=${file%.txt}          # strip off the suffix
  number=${number#time_step_}  # strip off the prefix
  if [[ $number -gt 0 ]]; then
    mv "$file" "time_step_$[number+2000].txt"
  else
    echo "ERROR: $file couldn't be processed" >&2
  fi
done

这样做的好处是可以在shell中执行除mv之外的所有操作,因此不会启动任何不必要的外部进程。当然,你的sed管道不会造成很多问题。如果你想(考虑到上面的ParsingLS链接),你可以使用sed来减少bash模式匹配,使这个可移植到非Bash shell。没有错误检查,它可能如下所示:

ls time_step_*.txt | sed -r 's/^(.*_)([0-9]+)(.*)/\2 &/' | while read number file; do
  mv "$file" "time_step_$((number+2000)).txt"
done

这可以通过将time_step_12.txt这样的文件名转换为12 time_step_12.txt这样的字符串来实现,这样两个单独的单词就可以通过while读入单独的变量中。请注意,如果数字不是纯数字,失败。

希望这是有教育意义的。 : - )