How to Use yq to Read, Update, and Merge YAML Files
Updated
yq is a command-line processor that uses jq-like syntax to read and modify YAML, JSON, XML, INI, properties, CSV, and TSV files. To read a value, run yq '.a.b[0].c' file.yaml; to update a file in place, add the -i flag; to merge files, use load() with * or combine ea with ireduce. The examples below assume yq v4.x and a file named file.yaml containing nested keys, arrays, and comments.
Read a value from a file
Pass an expression and a filename. The expression is a path into the document, and yq prints the matching value.
yq '.a.b[0].c' file.yaml
- Input:
file.yamlwith a structure likea: {b: [{c: ...}]}. - Action: yq evaluates the path expression.
- Expected result: the value at
.a.b[0].cis printed to stdout. The file is not changed.
You can also pipe the document in through STDIN instead of naming a file:
yq '.a.b[0].c' < file.yaml
This is useful when another command produces the YAML. The expression and output behavior are the same.
Update a YAML file in place
Add -i to write the result back to the same file. Without -i, yq prints the modified document to stdout and leaves the file untouched.
yq -i '.a.b[0].c = "cool"' file.yaml
- Input: the existing
file.yaml. - Action: the assignment sets
.a.b[0].cto the stringcool, and-ioverwrites the file. - Expected result:
file.yamlnow contains the new value; other content is preserved as far as yq can preserve it.
To update from an environment variable, use strenv() so the value is read as a string:
NAME=mike yq -i '.a.b[0].c = strenv(NAME)' file.yaml
- Input: the environment variable
NAMEset tomike. - Action:
strenv(NAME)resolves to the variable's value at evaluation time. - Expected result:
.a.b[0].cbecomesmikein the file.
This pattern is handy in scripts and CI, where values come from the environment rather than being hard-coded.
To find and update an item inside an array, select the element first and then assign. The documentation points to recipes and the full docs for concrete array examples; the general shape is a select/path expression followed by = value, run with -i to persist the change.
Merge multiple files
There are two documented approaches, and they behave differently.
Merge two named files with load() and *
yq -n 'load("file1.yaml") * load("file2.yaml")'
- Input: two files, loaded explicitly by name.
- Action:
-nmeans "no input file"; the expression loads both documents and*merges them. - Expected result: the merged document is printed to stdout.
Merge many files with a glob, ea, and ireduce
yq ea '. as $item ireduce ({}; . * $item )' path/to/*.yml
- Input: every
.ymlfile matching the glob. - Action:
eaevaluates all files at once instead of in sequence;ireducefolds them one by one into an accumulator starting from{}, merging each with*. - Expected result: a single merged document printed to stdout.
The ea flag matters here: the docs note it evaluates all files at once rather than in sequence, which is what makes the reduce over the whole set work as intended.
Things to watch for
- Comments and whitespace: yq tries to preserve comment positions and whitespace, but it does not handle every scenario. If formatting matters, check the output before committing.
- PowerShell quoting: PowerShell has its own quoting rules that can interfere with yq expressions. The docs point to tips and tricks for common problems and solutions.
- Coverage vs. jq: yq uses jq-like syntax but does not support everything jq does. The most common operations and functions are supported, and more are added over time.
- Installation: yq is written in Go, so you can download a dependency-free binary for your platform, or install via package managers, Docker, or Podman. The GitHub page lists the available methods.
For more examples, see the recipes and the full documentation; the discussions cover common questions.