【问题标题】:Creating a JSON object with name of the JSON file and its content in bash使用 JSON 文件的名称及其在 bash 中的内容创建 JSON 对象
【发布时间】:2020-09-21 04:36:31
【问题描述】:

我的目录中有几个.json 文件。如果我这样做:

find . -name '*.json' -exec echo "{\"filename\": \"{}\", \"content\": `cat {}` }," \;

我明白了:

{"filename": "./a.json", "content":  },
{"filename": "./b.json", "content":  },

但是,如果我这样做:

find . -name '*.json' -exec echo "{\"filename\": \"{}\", \"content\": cat {} }," \;

我明白了:

{"filename": "./a.json", "content": cat ./a.json },
{"filename": "./b.json", "content": cat ./b.json },

那么如何使a.jsonb.json 内容正确cated?

顺便说一句,如果我这样做:

find . -name '*.json' -exec cat {} \;

json文件在控制台打印正确,所以我知道文件内容是有效的。

【问题讨论】:

  • 不要尝试通过连接字符串来创建 JSON。使用jq 实用程序。
  • 我很乐意接受jq 的回答,因为我正在尝试做的事情。
  • @Inian 会在多个子目录中,文件名也会包含空格。

标签: bash find echo jq cat


【解决方案1】:

用简单的

$ cat a.json
{ "a":123 }
$ cat b.json
{ "b":234 }
$ cat "foo/bar/base/c c.json"
{ "c": 456 }
$ shopt -s globstar # enable recursion with '**'
$ for i in **/*.json; do
    cat<<EOF
    { "filename": "$i", "content": $(cat "$i") }
EOF
done | tee file.json
$ cat file.json
{ "filename": "a.json", "content": {"a":123} }
{ "filename": "b.json", "content": {"b":234} }
{ "filename": "foo/bar/base/c c.json", "content": { "c": 456 } }

【讨论】:

  • 如果文件名包含空格,这将不起作用。这是我最开始的。只有当失败时,我才使用基于find 的方法。另外,我在子目录中也有文件。
  • 这样你“输”了find。我认为如果for 迭代find 的输出行会更好
  • 添加了文件名中带有空格的文件,正确引用不用担心
  • 而且不需要在这里使用 bash 递归“查找”
  • 谢谢。接受了答案。只是为了完成,你能在每行的末尾添加一个,吗?
【解决方案2】:

使用bash 而不使用find,您可以执行以下操作。可以使用nullglobglobstar进行递归JSON文件名遍历

shopt -s nullglob globstar

默认情况下jq 提供了一个函数input_filename 打印当前正在处理的文件名。文档说,只要语言环境是UTF-8

,它就应该可以正常工作
jq '{ filename: input_filename, content: . }' **/*.json

要在对象条目之间使用逗号,请将-n 标志与inputs 一起使用,并将整个结果放入数组[..]

jq -n '[inputs | { filename: input_filename, content: . }]' **/*.json

对于同一行的紧凑输出,使用-c 标志作为jq -c '..'

【讨论】:

  • -n use 'null' as the single input value; 你能简单解释一下-n 标志在最后一个命令的上下文中是如何工作的吗?
  • @Philippe:-n 构造通常用于从头构造 JSON 对象。在上面的示例中,filenamecontent 是新创建的。新建 JSON 时,inputs 提供了所有文件的内容。由于我们没有使用 slurp 模式,因此过滤器应用于每个对象,input_filename 获取当前处理的文件的名称(内部)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
  • 2019-01-26
  • 2018-12-27
  • 1970-01-01
  • 2017-01-28
相关资源
最近更新 更多