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
notis a regular filter, use it like… | notWith the
-eflag, yq provides a way to transform its output into an exit status. From the manual:Thus, it suffices to take the boolean values from
hasandnot, and there's no need toselectthe content (unless you want to further process it). Here's one example using this flag in combination with anifstatement in the shell, and on a file stored in the shell variable$file.stdoutandstderrare suppressed to not interfere.Then traverse down the document using
.., and do the above if there'sanymatch:[.. | …] | any. Here's the full filter: