由于某种原因,该脚本为每个原始文件输出三个文件,而不是一个。
肯定是犯了一些微不足道的错误——我对此还不熟悉!
如果有人能解释为什么会发生这种情况,我将不胜感激。
脚本:-
for f in *.txt
do
noOfRows=$(cat $f | wc -l)
relevantRows=$(expr $noOfRows - 5)
head -n $relevantRows $f | tee ${f%.txt}-Amended.txt
done
ls 命令的结果:-
E12-5_F2_NEG-Amended-Amended-Amended.txt E12-5_M3_POS-Amended-Amended-Amended.txt
E12-5_F2_NEG-Amended-Amended.txt E12-5_M3_POS-Amended-Amended.txt
E12-5_F2_NEG-Amended.txt E12-5_M3_POS-Amended.txt
E12-5_F2_NEG.txt E12-5_M3_POS.txt
E12-5_F2_POS-Amended-Amended-Amended.txt E12-5_M4_NEG-Amended-Amended-Amended.txt
E12-5_F2_POS-Amended-Amended.txt E12-5_M4_NEG-Amended-Amended.txt
E12-5_F2_POS-Amended.txt E12-5_M4_NEG-Amended.txt
E12-5_F2_POS.txt E12-5_M4_NEG.txt
E12-5_F5_NEG-Amended-Amended-Amended.txt E12-5_M4_POS-Amended-Amended-Amended.txt
E12-5_F5_NEG-Amended-Amended.txt E12-5_M4_POS-Amended-Amended.txt
E12-5_F5_NEG-Amended.txt E12-5_M4_POS-Amended.txt
E12-5_F5_NEG.txt E12-5_M4_POS.txt
E12-5_F5_POS-Amended-Amended-Amended.txt E12-5_M7_NEG-Amended-Amended-Amended.txt
E12-5_F5_POS-Amended-Amended.txt E12-5_M7_NEG-Amended-Amended.txt
E12-5_F5_POS-Amended.txt E12-5_M7_NEG-Amended.txt
E12-5_F5_POS.txt E12-5_M7_NEG.txt
E12-5_M3_NEG-Amended-Amended-Amended.txt E12-5_M7_POS-Amended-Amended-Amended.txt
E12-5_M3_NEG-Amended-Amended.txt E12-5_M7_POS-Amended-Amended.txt
E12-5_M3_NEG-Amended.txt E12-5_M7_POS-Amended.txt
E12-5_M3_NEG.txt E12-5_M7_POS.txt
非常感谢,亚当
答案1
该脚本为每个原始文件输出三个文件...如果有人能解释为什么会发生这种情况,我将不胜感激。
由于以E12-5_F2_NEG-Amended.txt
结尾,.txt
下次运行时脚本将拾取它。
这三重结果表明您在调试脚本时运行了三次。
如果脚本输出到$f.new
而不是${f%.txt}-Amended.txt
,则不会遇到这个问题。
或者放在rm *Amended.txt
程序的开头。如果目录中有大量文件,则在较旧的 Unix 版本上可能会很慢。
另一个选择是将文件输出到子目录中(类似于"new/${f%.txt}.Amended.txt"
)
答案2
您只需一行代码即可完成脚本所要实现的功能:
head --lines=-5 input.txt > output.txt
在 for 循环中:
for f in *.txt; do head --lines=-5 "$f" > "${f%.txt}-Amended.txt"; done
如果愿意,您可以使用-n -5
而不是来节省输入时间。--lines=-5
正如 RedGrittyBrick 指出的那样,每个输入有三个文件的原因可能是因为您多次运行了该脚本,并且由于输出以 .txt 结尾,因此它们被连续脚本的 *.txt glob 拾取。
现在我将批评你的具体剧本。
noOfRows=$(cat $f | wc -l)
这确实猫的无用用途; 而不是cat $f | wc -l
,使用wc -l "$f"
。在这个特定的脚本中,这可能不是那么重要,但最好不要养成坏习惯。说到坏习惯:始终引用变量例如"$f"
。这将确保文件名即使包含空格也会被视为单个参数。
relevantRows=$(expr $noOfRows - 5)
这里其实没有什么问题,尽管我通常更喜欢使用类似
relevantRows=$((noOfRows-5))
据我所知,两者之间没有性能差异,但我发现 bash 的方式更美观;更重要的是,我描述的方式是在 POSIX 中定义的,因此更便携仅在 bash 中(因此如果您需要将脚本移植到不同的 shell,请不要使用此功能),最好的在脚本中执行此操作的方法是使用 let:
let noOfRows-=5
...这会从变量 $noOfRows 包含的数字中减去 5,这意味着不需要创建变量 $relevantRows。
head -n $relevantRows $f | tee ${f%.txt}-Amended.txt
这是正确的做法如果您希望将输出显示在命令行上,并将其放入输出文件中。否则,只需使用>
将 stdout 重定向到文件即可。