Reputation: 4750
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.
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: {}
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
Upvotes: 0
Views: 289
Reputation: 36033
not
is a regular filter, use it like … | not
.RunningProcess | (has("substring|export") and (has("CmdLine|regex") | not))
With the -e
flag, yq provides a way to transform its output into an exit status. From the manual:
-e
,--exit-status
set exit status if there are no matches or null or false is returned
Thus, it suffices to take the boolean values from has
and not
, and there's no need to select
the content (unless you want to further process it). Here's one example using this flag in combination with an if
statement in the shell, and on a file stored in the shell variable $file
. stdout
and stderr
are suppressed to not interfere.
filter='.RunningProcess | (has("substring|export") and (has("CmdLine|regex") | not))'
if yq -e "$filter" "$file" &>/dev/null
then echo "$file matches"
# else echo "$file does not match"
fi
The
RunningProcess
map can occur anywhere in the YAML document (it doesn't need to be in the root), but the other two keys must be immediate children of theRunningProcess
map.
Then traverse down the document using ..
, and do the above if there's any
match: [.. | …] | any
. Here's the full filter:
[.. | .RunningProcess | (has("substring|export") and (has("CmdLine|regex") | not))] | any
Upvotes: 0