I have two yaml files:
key: value
configmap:
data:
foo: bar
app: test
config:
testKey: testValue
I want to update file1.yaml's configmap.data with file2.yaml's config and save it back in file1.yaml so file1.yaml becomes:
key: value
configmap:
data:
testKey: testValue
How can I do this?
I tried the yq command
yq -i e '(select(fileIndex==0).configmap.data = select(fileIndex==1).config)' 'file1.yaml' 'file2.yaml'
But I got the following output, which appended the content of file1.yaml instead of updating it
key: value
configmap:
data:
foo: bar
---
app: test
config:
testKey: testValue
Please note that you are using mikefarah/yq (as opposed to kislyuk/yq which goes by the same name and can also be referenced by the
yqtag, but using it would require a very different solution of this problem).You can use the
loadfunction to load the contents of another file, then just assign the values of and to the right fields:Add the
-iflag to save the changes back into the primary input file (file1.yaml).Tested with mikefarah/yq version v4.34.2. (Note that since version 4.18.1, the
eval/ecommand is the default command, and no longer needs to be specified.)If you needed to specify the file names on shell level, e.g. from variables (which is trivial if they are plain arguments, but not so much if they have become part of the filter code), be aware that injecting them into the code string isn't good practice and creates unnecessary vulnerabilities. Instead, set environment variables, and use the
strenvfunction to read them:However, if you're for some reason restricted to provide all files as parameters, your approach of using
fileIndex/file_index/fiis indeed the way to go. Use theeval-all/eacommand to gather all sources into the same main context, and either reduce eventually to the target file's sub-context by appending anotherselectfilter (closest to your approach), or reduce before the assignment (breakselect(fi==0).xxx =intoselect(fi==0) | .xxx =) yet after presetting a variable to carry over a value from another sub-context: