3

I'm having an interesting issue. I'm using jq to minify JSON from a batch script, and I want it to replace the file it reads from. While there is probably a better solution, this, while it should work on paper, it does not work in practice.

Works:

for /R %%f in (*.json) do (
    ECHO Minifying JSON file "%%f"
    (ECHO Hello) 1> "%%f"
)

Output Files:

Hello


Shows that the redirect works

for /R %%f in (*.json) do (
    ECHO Minifying JSON file "%%f"
    ("path\to\jq" . --unbuffered --compact-output "%%f" && ECHO Hello) 1> "%%f"
)

Output Files:

Hello


Shows that jq produces output

for /R %%f in (*.json) do (
    ECHO Minifying JSON file "%%f"
    "path\to\jq" . --unbuffered --compact-output "%%f"
)

Output in CMD Window: Contents of each JSON file, minified (just like I want it)


What I'm trying to do

for /R %%f in (*.json) do (
    ECHO Minifying JSON file "%%f"
    ("path\to\jq" . --unbuffered --compact-output "%%f") 1> "%%f"
)

Output Files:

As you can see, there is no JSON present, minified or otherwise.


On the answer

@peak gave a workaround using PowerShell. In my situation, I came out with the following:

for /R %%f in (*.json) do (
    ECHO Minifying JSON file "%%f"
    powershell -Command "& {.\..\info\jq . --unbuffered --compact-output \"%%f\"|Set-Content \"%%f\"}"
)

This outputs the correct, minified JSON. What I'm doing here is invoking PowerShell to handle the minification, and using the Set-Content cmdlet.

peak
  • 105,803
  • 17
  • 152
  • 177
BellCube
  • 43
  • 1
  • 6

3 Answers3

2

You can't overwrite the file you are reading from, because the first action will be the (re)creation of the file by the redirection, then jq will read from an empty file.

Just redirect to a temporary file and replace the original file after finishing.

jeb
  • 78,592
  • 17
  • 171
  • 225
1

Even if it works or seem to work, blindly overwriting an input file using output redirection is usually a bad idea, or worse.

In an environment in which the (well-known) sponge utility is available, it can be used, but it looks like you might not have that luxury, so you might want to consider a more mundane approach using a temporary file.

PowerShell users can use SetContent: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/set-content?view=powershell-5.1

peak
  • 105,803
  • 17
  • 152
  • 177
0

The jq repo has a FAQ about this, here, under

: How can "in-place" editing of a JSON file be accomplished?

This says

...using tee or output redirection (>) to overwrite the input file is not recommended, even if it seems to work.

One easy fix suggested there is using sponge from moreutils. On macOS, one could do

$ brew install jq sponge

apt and npm can be used similarly.

With sponge, an in-place format of a json file would be

$ jq . my.json | sponge my.json
Clay Bridges
  • 11,602
  • 10
  • 68
  • 118