yq select: Filter by a Condition
yq select(condition) passes through only the nodes for which the condition is true.
Picking the container named app, or the document of a given kind, is a select() job. The Go yq select syntax matches jq closely, which is exactly why people confuse the two implementations.
What it does
select(expr) evaluates expr for each input node and keeps the node only when expr is truthy. Combined with array traversal .[], it filters lists; combined with documentIndex it filters documents. has("key") and == drive most conditions.
Common usage
# the container named "app"
yq '.spec.template.spec.containers[] | select(.name == "app")' deploy.yaml
# documents whose kind is Deployment
yq 'select(.kind == "Deployment")' all.yaml
# entries that have a "ports" key
yq '.services[] | select(has("ports"))' compose.yamlSelect conditions
| Expression | Keeps nodes where |
|---|---|
| select(.name == "app") | name equals "app" |
| select(.replicas > 1) | replicas is greater than 1 |
| select(has("ports")) | a ports key exists |
| select(.enabled == true) | enabled is boolean true |
| select(.tag | test("^v")) | tag matches a regex |
| select(documentIndex == 0) | this is the first document |
In CI
To read one container image into an output: IMG=$(yq '.spec.template.spec.containers[] | select(.name=="app") | .image' deploy.yaml); echo "image=$IMG" >> "$GITHUB_OUTPUT". select narrows to the node you want before extracting the field.
Common errors in CI
select(.name = "app") with a single = is an assignment, not a comparison; use == to compare. A select that returns nothing prints an empty line, which can look like success; pair with -e to make "no match" a non-zero exit. Because select syntax is shared with jq, the same expression "working" on kislyuk/yq does not confirm you are on mikefarah/yq; check yq --version when behavior diverges.