![jq - 通过管道将多个文件从“find”传输到 jq](https://linux22.com/image/201376/jq%20-%20%E9%80%9A%E8%BF%87%E7%AE%A1%E9%81%93%E5%B0%86%E5%A4%9A%E4%B8%AA%E6%96%87%E4%BB%B6%E4%BB%8E%E2%80%9Cfind%E2%80%9D%E4%BC%A0%E8%BE%93%E5%88%B0%20jq.png)
我尝试获取项目nodes_module 文件夹中特定节点包的所有版本。
有多个 package.json 文件,我希望“grep”“dependencies”下的文件:{“package-name”}
示例 json 文件:
{
"dependencies": {
"some-package": "^1.1.1",
"some-package": "^1.0.1",
"the-package-i-am-looking-for": "1.2.3"
},
"devDependencies": {
"some-package": "^1.7.3",
"some-package": "^2.0.0"
}
}
我想知道文件名和行(因此 grep)
所以理想情况下输出应该是这样的
some-package/package.json: "the-package-i-am-looking-for": "1.2.3"
some-other-package/package.json: "the-package-i-am-looking-for": "2.3.4"
我是unix管道的新手。这就是我想出的-这显然行不通
find . -name package.json | xargs cat | jq '.dependencies' | grep '"the-package-i-am-looking-for"'
感谢您的帮助
答案1
请注意,管道下游的任何部分都cat
无法访问原始文件的名称。从那时cat
起,到达管道的只是由一个或多个文件的内容组成的数据。
我相信以下可能是您正在寻找的内容:
find . -type f -name package.json \
-exec jq -r --arg pkg 'the-package-i-am-looking-for' \
'.dependencies | .[$pkg] // empty | [input_filename,$pkg,.] | @tsv' {} +
这会输出一个由三个字段组成的制表符分隔列表:
- 找到包的文件的路径名。
- 包名称。
- 版本字符串。
该find
命令jq
调用批次找到的路径名来生成输出,以便jq
完成尽可能少的调用。{} +
末尾的将会-exec
被收集的文件名替换。
该jq
调用通过解析输入文件、提取值.dependencies
、获取与我们正在查找的包相对应的键的版本字符串来生成输出,如果找到了某些内容,则输出当前文件名、包名称我们正在查询,以及版本字符串本身,作为使用制表符分隔的列表@tsv
。
可以修改输出格式以满足您的需要。您可以更改@tsv
为@csv
获取 CSV 格式的输出。
当前目录和名为 的目录中提供的文件副本(已更正格式问题)的示例dir
:
$ tree
.
|-- dir
| `-- package.json
`-- package.json
1 directory, 2 files
$ find . -type f -name package.json -exec jq -r --arg pkg 'the-package-i-am-looking-for' -e '.dependencies | .[$pkg] // empty | [input_filename,$pkg,.] | @tsv' {} +
./package.json the-package-i-am-looking-for 1.2.3
./dir/package.json the-package-i-am-looking-for 1.2.3
如果您觉得确实需要find
和之间的管道xargs
,则可以使用以下不可移植代码:
find . -type f -name package.json -print0 |
xargs -0 \
jq -r --arg pkg 'the-package-i-am-looking-for' \
'.dependencies | .[$pkg] // empty | [input_filename,$pkg,.] | @tsv'
与直接进行这一切相比,通过这种方式进行任何操作都不会获得任何好处find
。