I would like to search recursively through all .yaml
files in a directory and retrieve the paths to files with this extension that meet some requirements.
I want to get all files that match this requirement: The file contains a RunningProcess
map that contains a substring|export
key but no CmdLine|regex
key. The RunningProcess
map can occur anywhere in the YAML tree, but the other two keys must be immediate children of the RunningProcess
map.
I am using yq
version 4.35.2.
My terminology might not properly match the terms used in the official YAML specification, so I provide some examples below.
Examples
Example 1: The following YAML file should be included in the results:
RunningProcess:
substring|export: true
otherKey: true
OtherKey: {}
Example 2: The following YAML file should not be included in the results, since it contains the CmdLine|regex
key:
RunningProcess:
substring|export: true
CmdLine|regex: true
OtherKey: {}
Example 3: The following YAML file should not be included in the results, since it does not contain a RunningProcess
map:
OtherKey: {}
Example 4: The following YAML should be included in the results:
Outer:
RunningProcess:
substring|export: true
otherKey: true
OtherKey: {}
What I have tried
I know how to write a loop with find
to try each file at a time (as it seems yq
does not support recursive searching), so I was focusing on the yq
query.
I tried the query below, but I get an error message:
$ yq eval 'select(has("RunningProcess") and .RunningProcess | has("substring|export") and not .RunningProcess | has("CmdLine|regex"))' test_file.yaml
Error: bad expression, please check expression syntax
not
is a regular filter, use it like… | not
With the
-e
flag, yq provides a way to transform its output into an exit status. From the manual:Thus, it suffices to take the boolean values from
has
andnot
, and there's no need toselect
the content (unless you want to further process it). Here's one example using this flag in combination with anif
statement in the shell, and on a file stored in the shell variable$file
.stdout
andstderr
are suppressed to not interfere.Then traverse down the document using
..
, and do the above if there'sany
match:[.. | …] | any
. Here's the full filter: