我有大量文件要重命名,但似乎没有重命名功能

  • 本文关键字:重命名 功能 文件 file sed renaming
  • 更新时间 :
  • 英文 :


我一直在仔细研究,发现了"rename"one_answers"sed",我不是很精通计算机,但我已经尝试过了。到目前为止,我可以使用sed来找到我想要搜索的内容,但我无法找到如何用我真正想要的内容替换(希望这有意义)。

因此,场景:我有5000个文件,分为三批(2000、2000和1000),生成它们的程序总是从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

但是文件名本身没有改变我已经多次管理过同样的输出。

我想我理解管道和"保存"字符等,但正如我所说,我不太精通计算机,而且我对我读过的各种帖子中的术语感到困惑。

所有的帮助都非常感谢

所以。。。

首先,让我指出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不会做数学运算,但您真正想在这里使用的regex已经考虑到了整个输入文本。例如,在bash:中

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

结果是一组命令,您可以通过sh(或bash)通过管道传输,方法是将| sh添加到行的末尾,以便在验证这些命令是否正确后执行这些命令。注意-r选项,在许多实现中,它告诉sed将regex解释为ERE而不是BRE。如果这对您不起作用(因为您使用的是较旧的unix、SVR4等),请这样说,我们可以将regex转换为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

这样做的优点是,除了在外壳内执行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就可以将两个单独的单词读取为单独的变量。请注意,如果数字不是纯数字,则将出现故障。

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

这应该适用于第二批,然后对第三批执行+3000

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

最新更新