jq - 通过管道将多个文件从“find”传输到 jq

jq - 通过管道将多个文件从“find”传输到 jq

我尝试获取项目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' {} +

这会输出一个由三个字段组成的制表符分隔列表:

  1. 找到包的文件的路径名。
  2. 包名称。
  3. 版本字符串。

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

相关内容