bash: 如何将一个文件的多个副本快速复制到另一个文件中?

bash: how to copy multiple copies of one file into another fast?

我需要通过逐渐增大输入文件来对程序进行压力测试。我有一个输入文件 inputSmall.txt,我想将其复制 N 次,并将这些副本 cat 复制到同一个文件中。 N 是大文件。如果有什么比以下简单循环(例如 N=1000)更快的工作:

for i in {1..1000}
do 
    cat inputSmall.txt >> input1000.txt
done

我的机器有足够的磁盘 space 来存储 inputN.txt 非常大的 Ns 并且有很多 RAM,以备不时之需。

感谢

写的时候

for i in {1..1000}

你告诉 shell 首先将 1 到 1000 的所有数字写入命令缓冲区,然后遍历每个数字。对于大数字,这不仅速度慢,而且还会增加显着的内存需求(例如,参见 unix.se 处的 this post)。

在 bash 中,您可以使用以下语法避免所有这些情况:

for ((i=1; i<=1000;i++))

作为奖励,这允许边界是变量。

这样你可以更快地完成 "exponential",但是你需要一些额外的磁盘 space 来存放 tmp 文件。

input=

new=${input}.new.txt
tmp=${input}.tmp.txt

cat ${input} > ${new}
cat "" > ${tmp}

# 2^10=1024
for ((i=0; i<10 ; i++))
do
        cat ${new} >> ${tmp}
        cat ${tmp} >> ${new}
done

rm ${tmp}

cat是一个外部命令,而不是shell的一部分;像所有外部命令一样,启动它有很大的开销。类似地,运行 >>input1000.txt 是一个相当昂贵的文件系统操作——查找与目录关联的索引节点,打开它,然后(在离开作用域时)刷新内容并关闭文件。

这些事情只做一次会更有效率。


假设 inputSmall.txt 的最后一行以换行符结尾,下面的代码将正常工作,并且开销要小得多:

in=$(<inputSmall.txt)        # read the input file only once
exec 3>>input1000.txt        # open the output file only once

for ((i=0; i<1000; i++)); do
  printf '%s\n' "$in" >&3    # write the input from memory to the output fd
done
exec 3>&-                    # close the output fd