2

I try to get all versions of a specific node-package within a project nodes_module folder.

There are multiple package.json files and I wish to "grep" the ones under "dependencies": { "package-name" }

example json file:

{
  "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"
  }
}

I would like to know the filename and the line (therefor grep)

so ideally the output would look like this

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"

I'm new to the hole unix piping. this is what I came up with - which obviously does not work

find . -name package.json | xargs cat | jq '.dependencies' | grep '"the-package-i-am-looking-for"'

Thankful for any help

0

1 Answer 1

6

Note that none of the parts of your pipeline, downstream from cat, has access to the original file's name. From cat onward, it's just data consisting of the contents of one or several files that arrives on the pipe.

I believe that the following may be something like what you're looking for:

find . -type f -name package.json \
    -exec jq -r --arg pkg 'the-package-i-am-looking-for' \
        '.dependencies | .[$pkg] // empty | [input_filename,$pkg,.] | @tsv' {} +

This outputs a tab-delimited list consisting of three fields:

  1. The pathname of the file where the package was found.
  2. The package name.
  3. The version string.

The find command calls jq with batches of found pathnames to produce the output, so that as few jq invocations as possible are done. It's the {} + at the end of -exec that will be replaced by the collected filenames.

The jq call produces the output by parsing the input file(s), extracting the .dependencies value, getting the version string for the key corresponding to the package we're looking for, and if something was found, outputting the current filename, the package name that we are querying with, and the version string itself, as a tab-delimited list using @tsv.

The output format could be modified to suit your needs. You could change @tsv into @csv to get CSV-formatted output.

Example with copy of the provided file (with formatting issus corrected) in the current directory and in the directory called 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

If you felt like you really need a pipeline between find and xargs, you could use the following non-portable code:

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'

You gain nothing by doing it this way compared to doing it all from find directly.

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.