我一直在好好挖掘并发现"重命名"我不是很熟悉计算机,但我已经找到了我所发现的东西。 到目前为止 - 我能够使用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
但文件名本身并没有改变 我已经管理了相同的输出几次。
我想我了解管道和节省"人物等等,但就像我说的那样,不是很熟悉计算机,也不像我在读过的各种帖子上的术语感到困惑。
非常感谢所有人的帮助
答案 0 :(得分:1)
这适用于第二批,然后为第三批
执行+3000for 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
读入单独的变量中。请注意,如果数字不是纯数字,将失败。
希望这是有教育意义的。 : - )