$linuxjunkies
>

Use yq to Process YAML

Learn to read, filter, transform, and safely edit YAML files in place using mikefarah/yq — the Go-based jq equivalent for YAML.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • Basic familiarity with YAML syntax (keys, values, lists, nesting)
  • A terminal with sudo access for installation
  • curl or wget available for binary download if not using a package manager

yq is a lightweight, portable command-line YAML processor written in Go by Mike Farah. Think of it as jq for YAML — you can read, filter, update, and transform YAML files without writing a single line of Python or a throwaway script. This guide covers installation, the expression syntax, common transforms, and safe in-place editing.

Installation

There are several yq packages floating around. Make sure you install mikefarah/yq, not the Python-based yq wrapper that some distro repos still ship. The canonical way to get the right one is via the GitHub release binary or a package manager that tracks it explicitly.

Debian / Ubuntu

The version in older Ubuntu repos is the Python wrapper. Use the upstream binary instead:

sudo wget -qO /usr/local/bin/yq \
  https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
sudo chmod +x /usr/local/bin/yq
yq --version

Fedora / RHEL / Rocky

Fedora 36+ ships mikefarah/yq in the default repos:

sudo dnf install yq

On RHEL 8/9 or Rocky without the package, fall back to the binary method shown above.

Arch Linux

sudo pacman -S go-yq

The package is named go-yq to distinguish it from the Python variant.

Verify the right yq

yq --version
# Should print: yq (https://github.com/mikefarah/yq/) version v4.x.x

If you see a Python-based version string, remove it and install the binary manually.

Expression Basics

All yq expressions use a path syntax similar to jq. A dot (.) is the root document. Nested keys are accessed with dots: .spec.replicas. Arrays are zero-indexed: .items[0]. Wildcards and recursive descent (..) are supported.

Given this example file, app.yaml:

cat app.yaml
name: myapp
version: "1.4.2"
server:
  host: 0.0.0.0
  port: 8080
  tls: false
features:
  - auth
  - metrics
  - tracing

Read a single value

yq '.server.port' app.yaml
# 8080

Read a nested array element

yq '.features[1]' app.yaml
# metrics

Read all array elements

yq '.features[]' app.yaml

Common Transforms

Update a scalar value

Use the assignment operator = with the -e flag (evaluate) or pipe the result. To print the modified document without touching the file:

yq '.server.port = 9090' app.yaml

Toggle a boolean

yq '.server.tls = true' app.yaml

Add an item to an array

yq '.features += ["ratelimit"]' app.yaml

Delete a key

yq 'del(.server.tls)' app.yaml

Rename a key

yq does not have a direct rename operator. The idiomatic approach is to copy then delete:

yq '(.server.hostname = .server.host) | del(.server.host)' app.yaml

Merge two YAML files

Pass multiple files; yq processes them as a stream. To merge a patch file on top of a base:

yq '. *= load("patch.yaml")' base.yaml

The *= operator does a recursive merge, with right-hand values winning on conflicts.

Select array elements by condition

yq '.features[] | select(. == "auth")' app.yaml

Convert YAML to JSON

yq -o=json '.' app.yaml

Convert JSON to YAML

yq -p=json '.' data.json

Output a specific key as plain string (no quotes)

yq -r '.version' app.yaml
# 1.4.2

Editing Files In Place

The -i flag writes the result back to the original file. This is the most common source of mistakes — always test your expression without -i first.

Basic in-place update

yq -i '.server.port = 9090' app.yaml

Back up before editing

yq does not have a built-in backup suffix like sed -i.bak. Do it manually:

cp app.yaml app.yaml.bak
yq -i '.version = "1.5.0"' app.yaml

Edit multiple files at once

yq -i '.server.tls = true' config/*.yaml

Scripted multi-step edits

Chain expressions with | inside a single call to avoid multiple file passes:

yq -i '
  .version = "1.5.0" |
  .server.port = 9090 |
  .server.tls = true
' app.yaml

Working with Multi-Document YAML

Kubernetes manifests and many other files contain multiple documents separated by ---. yq handles them natively.

Select a specific document by index

yq 'select(di == 1)' multi.yaml

Update a field across all documents

yq -i '[.] | .[] | select(.kind == "Deployment") .spec.replicas = 3' k8s.yaml

Practical Kubernetes example: bump an image tag

yq -i '(
  select(.kind == "Deployment") |
  .spec.template.spec.containers[] |
  select(.name == "app")
).image = "myrepo/app:v2.1.0"' deployment.yaml

Verification

After any in-place edit, validate the file is still valid YAML and contains what you expect:

# Check it parses without error
yq '.' app.yaml > /dev/null && echo "Valid YAML"

# Spot-check the changed value
yq '.server.port' app.yaml
# 9090

Troubleshooting

Expression silently returns nothing

A path that does not exist returns null, not an error. Double-check your key names — YAML is case-sensitive. Use yq 'keys' app.yaml to list top-level keys and work down.

In-place edit produces an empty file

This almost always means the expression itself errored out. Run the same expression without -i first. If the terminal shows nothing or an error message, fix the expression before adding -i back.

Comments are stripped after editing

yq v4 preserves comments in most cases, but complex merges or expression chains can drop them. If comment preservation is critical, review the diff after editing and keep your expressions simple.

Type coercion surprises

YAML values like true, yes, and on are all parsed as booleans. If you need a literal string "true", quote it in your expression: .flag = "true". Check with yq '.flag | type' app.yaml.

tested on:Ubuntu 24.04Fedora 40Arch rollingDebian 12

Frequently asked questions

How do I tell if I have mikefarah/yq or the Python yq wrapper installed?
Run yq --version. The mikefarah version prints a URL containing github.com/mikefarah/yq and a v4.x.x version number. The Python wrapper prints something like yq x.x.x and references kislyuk/yq or a pip origin.
Does yq -i preserve YAML comments?
yq v4 makes a best effort to preserve comments, and succeeds in most straightforward edits. Complex chained expressions or merges can sometimes drop comments, so diff the file afterward if comments matter.
Can I use yq to edit JSON files directly?
Yes. Pass -p=json to parse JSON input and -o=json to emit JSON. You can then use the same path expressions you would on YAML.
How do I update a value only if the key already exists?
Wrap the assignment in a select: yq '(select(has("version")) | .version) = "2.0"' file.yaml — this silently skips files that lack the key.
Is there a way to validate YAML structure with yq?
yq itself only checks that a file is syntactically valid YAML; it has no schema validation. Pipe yq output to a dedicated tool like ajv or kubeconform for schema checks.

Related guides