【问题标题】:pasting many files to a single large file将多个文件粘贴到一个大文件中
【发布时间】:2024-01-10 08:32:01
【问题描述】:

我在1.txt 2.txt 3.txt 4.txt .......2000.txt 之类的目录中有许多文本文件,我想将它们粘贴到一个大文件中。

在这方面我做了类似的事情

paste *.txt > largefile.txt

但是上面的命令随机读取.txt文件,所以我需要依次读取文件并粘贴为1.txt 2.txt 3.txt....2000.txt 请为粘贴许多文件提出更好的解决方案。 感谢并期待收到您的来信。

【问题讨论】:

  • but the above command reads the .txt file randomly, 你确定吗?文件应该被排序,这意味着1.txt 10.txt 11.txt .... 100.txt 101.txt ... 1000.txt 1001.txt ... 2.txt ... etc。但它不应该是随机数。
  • 是的,先生,我确定
  • 那你能把ech paste *.txt的输出贴出来吗?你确定你使用的是 bash 吗? declare -p BASH_VERSION 的输出是什么?

标签: linux bash for-loop sh paste


【解决方案1】:

然后自己按数字对文件名进行排序。

printf "%s\n" *.txt | sort -n | xargs -d '\n' paste

处理多个文件时,您可以点击ulimit -n。在我的系统上ulimit -n1024,但这是一个软限制,可以像ulimit -n 99999 一样提高。

在不提高软限制的情况下,使用一个临时文件,该文件将在 ulimit -n 文件计数的每一“轮”中累积结果,例如:

touch accumulator.txt
... | xargs -d '\n' -n $(($(ulimit -n) - 1)) sh -c '
       paste accumulator.txt "$@" > accumulator.txt.sav;
       mv accumulator.txt.sav accumulator.txt
' _
cat accumulator.txt

【讨论】:

  • 存在超过 1000 个文件时会失败。它显示错误,如 paste: 1022.txt: Too many open files
  • 请提出更好的解决方案
  • paste: 1022.txt: Too many open files 呃,ulimit -n 一定很低。好吧,这是一次合并 1024 个文件然后将 1024 个文件合并在一起的唯一方法...:/ 但很可能您可以自己提出 ulimit -n,这是一个软限制。
【解决方案2】:

改为使用通配符* 枚举目录中的所有文件,如果您的文件名模式是按顺序排列的,您可以手动按顺序列出所有文件并连接到一个大文件。 * 枚举的输出顺序在不同的环境中可能看起来不同,因为它不会像您期望的那样工作。

下面是一个简单的例子

$ for i in `seq 20`;do echo $i > $i.txt;done
# create 20 test files, 1.txt, 2.txt, ..., 20.txt with number 1 to 20 in each file respectively
$ cat {1..20}.txt
# show content of all file in order 1.txt, 2.txt, ..., 20.txt
$ cat {1..20}.txt > 1_20.txt
# concatenate them to a large file named 1_20.txt

【讨论】:

    【解决方案3】:

    在 bash 或任何其他 shell 中,glob 扩展是按字典顺序完成的。当对文件进行编号时,这可悲地意味着11.txt < 1.txt < 2.txt。这种奇怪的排序来自于这样一个事实,在字典上,1 < . (-character ("."))。

    所以这里有几种按顺序操作文件的方法:

    重命名所有文件:

    for i in *.txt; do mv "$i" "$(sprintf "%0.5d.txt" ${i%.*}"); done
    paste *.txt
    

    使用大括号扩展:

    大括号扩展是一种允许生成任意字符串的机制。对于整数,您可以使用{n..m} 生成从nm 的所有数字或{n..m..s} 以生成从nm 的所有数字,步骤为s

    paste {1..2000}.txt
    

    这里的缺点是文件可能丢失(例如1234.txt)。所以你可以做

    shopt -s extglob; paste ?({1..2000}.txt)
    

    模式?(pattern) 匹配零个或一个全局匹配。所以这将排除丢失的文件但保持顺序。

    【讨论】: