Sometimes I need the full Composer dependency name but I only know part of it. For example, I may know Block X-ray Attributes is a Composer dependency but I don’t remember the full package name. While I could open the composer.json
file and find the dependency, I can also leverage jq to do the work for me.
Find Dependency and Version
If I want to find the Composer dependencies with xray
in the name, I can run
jq --raw-output \
'.require | to_entries[] | select(.key | contains("xray")) | [ .key, .value ] | join(":")' \
composer.json
On my project, this will return something like
wpackagist-plugin/block-xray-attributes:^1.1.1
Find Multiple Dependencies
The query above will return all of the dependencies that match our string.
For example, if we wanted to find all of the dependencies from wpackagist
, we can use that in our command instead of xray
.
jq --raw-output \
'.require | to_entries[] | select(.key | contains("wpackagist")) | [ .key, .value ] | join(":")' \
composer.json
Which gives us something like
wpackagist-plugin/block-xray-attributes:^1.1.1
wpackagist-plugin/stop-emails:^1.2.0
wpackagist-plugin/modify-comment-parent:^1.0.0
How I Built this Query
Base Query
I started with the base jq
query
jq '.' composer.json
This query tells jq
to read composer.json
and return the whole object ('.'
)
Require Key
We only want the entries in the .require
section, so we add that to our query.
jq '.require' composer.json
Now we have an object where the keys are the package names and the values are the version constraint.
{
"composer/installers":"^1.6",
"wpackagist-plugin/block-xray-attributes": "^1.1.1",
"wpackagist-plugin/stop-emails": "^1.2.0",
"wpackagist-plugin/modify-comment-parent": "^1.0.0"
}
Make Each Key/Value a New Object
jq '.require | to_entries[]' composer.json
Using to_entries, each key/value pair becomes a new object
{
"key": "composer/installers",
"value": "^1.6"
}
{
"key": "wpackagist-plugin/block-xray-attributes",
"value": "^1.1.1"
}
{
"key": "wpackagist-plugin/stop-emails",
"value": "^1.2.0"
}
{
"key": "wpackagist-plugin/modify-comment-parent",
"value": "^1.0.0"
}
Filter the Results
jq \
'.require | to_entries[] | select(.key | contains("xray"))' \
composer.json
Using select and contains() we select the entries where key contains our string (xray
) in the key.
{
"key": "wpackagist-plugin/block-xray-attributes",
"value": "^1.1.1"
}
Turn the Result into an Array
jq \
'.require | to_entries[] | select(.key | contains("xray")) | [ .key, .value ] ' \
composer.json
Using the Array Construction, we turn the result(s) into an array where the first element is the key (the package name) and the second element is the value (the version constraint).
[
"wpackagist-plugin/block-xray-attributes",
"^1.1.1"
]
Join the Elements of the Array with a colon (:)
jq \
'.require | to_entries[] | select(.key | contains("xray")) | [ .key, .value ] | join(":")' \
composer.json
We use the join() function to turn each array into a string.
"wpackagist-plugin/block-xray-attributes:^1.1.1"
Finally Eliminate the Quotes
jq --raw-output \
'.require | to_entries[] | select(.key | contains("xray")) | [ .key, .value ] | join(":")' \
composer.json
We add the --raw-output
flag when invoking jq
to eliminate the quotes
wpackagist-plugin/block-xray-attributes:^1.1.1
Why Not Use Grep
At this point you might be saying, we could get this same result with a grep command
grep 'xray' composer.json
This is true and in many cases it is easier to use grep
. The power of jq
comes through when you want to deal with part of the line.
Find Just the Package Name
This whole article started with me and my issue of me needing the full package name. This modified version of the command returns just the package name(s).
jq --raw-output \
'.require | to_entries[] | select(.key | contains("xray")) | .key' \
composer.json
Alias
Because I’d rather not type this each time, I’ve created an alias (technically a function) in my ~/.zshrc
, called jqcfind
I’m using the --arg
option to pass the first parameter ($1
) into jq
as the variable $x
.
function jqcfind() {
jq --raw-output --arg x "$1" \
'.require | to_entries[] | select(.key | contains($x)) | .key' \
composer.json | tee >(pbcopy)
}
I’m also using tee and pbcopy (since I’m on a Mac) to both print the result to the screen and copy it to my clipboard.
For example:
jqcfind xray
finds the packages with “xray” in the name and outputs the full package name (and copies it to the clipboard).
Leave a Reply