将多个文件与分隔符合并为一个文件

Combine several files, with a separator, into one file

我有几个 (~300,000) 个单独的 JSON 对象文件,我想将它们组合成一个 JSON 数组文件。假设它们都在“~/data_files”位置,我如何在 linux 上执行此操作?

文件A

{
  name: "Test",
  age: 23
}

文件B

{
  name: "Foo",
  age: 5
}

文件C

{
  name: "Bar",
  age: 5
}

示例输出:(以方括号开始和结束,并在对象之间添加逗号)

[
    {
      name: "Test",
      age: 23
    },
    {
      name: "Foo",
      age: 5
    },
    {
      name: "Bar",
      age: 5
    }
]

我试过的:

我知道我可以使用 cat 来合并一堆文件,但不确定如何对目录中的所有文件执行此操作,但正在尝试解决这个问题。还试图弄清楚如何在我正在连接的文件之间设置 ,,还没有看到它的命令。

一个简单的 for 循环和几个 sed 即可

$ echo "[" > all; 
  for f in file{A,B,C}; 
  do 
     sed 's/^/\t/;$s/$/,/' "$f" >> all; 
  done; 
  sed -i '$s/,/\n]/' all

$ cat all
[
 {
   name: "Test",
   age: 23
 },
 {
   name: "Foo",
   age: 5
 },
 {
   name: "Bar",
   age: 5
 }
]

或与标准输出相同

$ echo "["; for f in file{A,B,C}; do sed 's/^/\t/;$s/$/,/' "$f"; done |
sed `'$s/,/\n]/'`

到 运行 将目录中的所有文件更改 file{A,B,C}*

即使文件数量超过 300K,此脚本也应该可以运行。此脚本也比 sed 解决方案更快,因为输入文件未被修改。

#!/bin/sh
tmp="/dev/shm/${USER}.find.tmp"
out='all.json'
find . -maxdepth 1 -name file\* > ${tmp}
echo '[' > ${out}
for f in $(head -n -1 ${tmp})
do
  cat ${f} >> ${out}
  echo ',' >> ${out}
done
f=$(tail -n 1 ${tmp})
cat ${f} >> ${out}
echo ']' >> ${out}
rm -f -- ${tmp}

由于您似乎对 unix 有点陌生,我将尝试为您提供一个简单且不会引入太多新概念的解决方案。我会把聪明和新颖留给其他 post 人。这个解决方案将非常高效,因为我所做的只是将文件流式传输到文件中。

首先,我们将在主目录中创建一个包含方括号的新文件。
echo "[" > ~/tmp.json

现在我们遍历 data_files 目录中的所有文件 并将它们附加到我们的新文件中。 >> 会将它们添加到已经存在的内容中。如果您使用 > 那么文件每次都会被覆盖。 echo 会在 cat 输出完文件后添加一个逗号。
for i in ~/data_files/*; do cat $i;echo ","; done >> ~/tmp.json

所以现在我们将您的 300k 个文件放在一个名为 tmp.json 的文件中,每个条目都用逗号分隔,但文件的最后一行也是逗号,这不是我们想要的。
下面的 sed 命令的行为类似于 cat 除了 '$d' 告诉它省略文件的最后一行。
所以我们创建一个包含所有内容的新文件但是我们临时文件的最后一行。
sed '$d' ~/tmp.json > ~/finished.json

我们需要关闭方括号
echo "]" >> ~/finished.json

最后我们删除我们的临时文件 rm ~/tmp.json

我们完成了。

[
{
    name: "Test",
    age: 23
}
,
{
    name: "Foo",
    age: 5
}
,
{
    name: "Bar",
    age: 5
}
]

快速浏览一下 this post 关于漂亮打印的内容 json 将指向一个命令行工具,该工具将获取您的 finished.json 文件并将其转换为 正是你要求的输出。

和 python 版本的完整性:

import os, sys

dir = sys.argv[1]

print "["
for fn in os.listdir(dir):
    with open(dir + '/'  + fn, 'r') as f:
        read_data = f.read()
        print read_data,
    print ","
print "]"

jc.. 使用 jq,这是或应该是最佳实践

$ cat <<eof | jq -s
> { "key": 1 }
> { "key2": 2 }
> { "key3": 3 }
> eof
[
  {
    "key": 1
  },
  {
    "key2": 2
  },
  {
    "key3": 3
  }
]

如果您的要求只是将 json 个对象推入队列,那么任何其他建议充其量都是幼稚的,这不是基于意见的陈述。