Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inputs skips the first file specified #2394

Closed
stanio opened this issue Jan 6, 2022 · 8 comments
Closed

inputs skips the first file specified #2394

stanio opened this issue Jan 6, 2022 · 8 comments

Comments

@stanio
Copy link

stanio commented Jan 6, 2022

I have a number (few hundred) of .json files which content is array (possibly empty) of objects, and I'm using the following command to merge them:

jq '[inputs | .[]]' *.json > merged.json

I've discovered the content of one of the files is missing from the result.

To Reproduce

Have three JSON files in a directory:

foo.json
bar.json
baz.json

Issue a command:

jq '[inputs | input_filename]' foo.json bar.json baz.json

The result I'm getting:

[
  "bar.json",
  "baz.json"
]

Expected behavior

A result of:

[
  "foo.json",
  "bar.json",
  "baz.json"
]

Environment (please complete the following information):

  • Windows 10 64-bit (21H1 build 19043.1415)
  • jq version 1.6

Additional context

I'm running in a Git-bash console:

$ jq '[inputs | input_filename]' foo.json
[]
$ jq '[inputs | input_filename]' foo.json foo.json bar.json baz.json
[
  "foo.json",
  "bar.json",
  "baz.json"
]
$ jq '[inputs | input_filename]' bar.json foo.json bar.json baz.json
[
  "foo.json",
  "bar.json",
  "baz.json"
]

input also appears to act weird:

$ jq '[input | input_filename]' foo.json
jq: error (at <unknown>): break
$ jq '[input | input_filename]' foo.json bar.json
[
  "bar.json"
]
$ jq '[input | input_filename]' foo.json bar.json baz.json
[
  "bar.json"
]
jq: error (at <unknown>): break
$ jq '[input | input_filename]' bar.json foo.json bar.json baz.json
[
  "foo.json"
]
[
  "baz.json"
]

(I'm not really sure what's the expected outcome with the last one.)


https://stedolan.github.io/jq/manual/v1.6/#IO

@wader
Copy link
Member

wader commented Jan 6, 2022

Hey, try to add -n, otherwise jq will implicitly read one input.

$ jq ".,inputs" <(echo 1) <(echo 2)
1
2
$ jq -n "inputs" <(echo 1) <(echo 2)
1
2

Might feel be a bit unintuitive but i think it makes sense.

@stanio
Copy link
Author

stanio commented Jan 6, 2022

Thank you very much, @wader! Yeah, it's pretty unintuitive to me – not a jq-guru, and it gets even more confusing after reading the doc:

  • --null-input/-n:

Don't read any input at all!...

😄

I confirm adding -n appears to work for me:

$ jq -n "[inputs | input_filename]" foo.json bar.json baz.json
[
  "foo.json",
  "bar.json",
  "baz.json"
]

$ jq -n '[input | input_filename]' foo.json bar.json baz.json
[
  "foo.json"
]

@wader
Copy link
Member

wader commented Jan 6, 2022

Yeah the documentation could be clearer, but i understand it's a bit tricky to explain. It makes sense if you think about how jq . file works, if it did not read one input implicitly you would have to write jq "input | .." file.

How it works is that jq more or less handle all the input files as if they were one big concatenated file. Then it reads one JSON value (that can span between files) at the time until the end, and you can also explicitly read values by calling input (read one value) and inputs (read and output all remaining values one at a time). The reason i happen to know a lot about this is because i reimplement most of it for a tool based on jq :)

Here is an example explain most of it:

$ jq -n '[input,input,try input catch .]' <(echo -n 1) <(echo 2) <(echo 3)
[
  12,
  3,
  "break"
]

I recommend also look into -s (slurp) and -R (raw string input) which can be very useful.

@stanio
Copy link
Author

stanio commented Jan 7, 2022

Thank you again for providing an additional explanation. The issue is resolved and appears to work as designed. Please close at your discretion.

I guess an explicit reference to the -n/--null-input option could be included in the IO section of the manual as it is an option most likely (if not mandatory) needed when using input and/or inputs, as far as I understand.

@stanio
Copy link
Author

stanio commented Jan 7, 2022

Some alternative approaches to my original use case: Merge/concatenate arrays from multiple files

Using --slurp:

jq -s "[.[][]]" foo.json bar.json baz.json

Couldn't find a use for -R/--raw-input in this case but I hope I'll remember it when I need it. 😃

@wader
Copy link
Member

wader commented Jan 7, 2022

Thank you again for providing an additional explanation. The issue is resolved and appears to work as designed. Please close at your discretion.

No problem. I think you have to close as i'm not a collaborator on this repo.

I guess an explicit reference to the -n/--null-input option could be included in the IO section of the manual as it is an option most likely (if not mandatory) needed when using input and/or inputs, as far as I understand.

Yes that would be good i think. Created #2395

@wader
Copy link
Member

wader commented Jan 7, 2022

Some alternative approaches to my original use case: Merge/concatenate arrays from multiple files

Using --slurp:

jq -s "[.[][]]" foo.json bar.json baz.json

👍

If you want to be more explicit you can also use map(.[]) or maybe even just add in this case.

Couldn't find a use for -R/--raw-input in this case but I hope I'll remember it when I need it. 😃

There is also the combination -sR 😄

@stanio stanio closed this as completed Jan 7, 2022
@stanio
Copy link
Author

stanio commented Jan 7, 2022

KISS:

jq -s "add" foo.json bar.json baz.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants