8

This question already has an answer here:

I am trying to run a command in bash where I have a command 1 which accepts a large amount content through stdin and then outputs that content to a file.txt, however, command 1 generates a stream of content and apparently file.txt gets created as soon as command 1 starts and then gets updated once command 1 finishes with the correct output.

echo 'a lot of content' | command 1 > file.txt

The problem is that I only want to create or touch file.txt once command 1 is completely finished.

Is there any way to achieve that?

Edit:

Use-case: I am using a web development server that gets refreshed every time a file changes, so I am doing some pre-processing before really updating the file.

The problem with the above command is that if the file is updated or create with empty content the server refreshes instantly, having an empty page, so I really wanted to wait for the post processing to finish (let's say it takes about 4 seconds) and only then touch file.txt so it is correctly rendered on the page.

So there's only one command I need to run here, which is command 1 and then, after file.txt is updated, my web development server will refresh automatically.

marked as duplicate by Gilles bash Aug 29 '16 at 17:49

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Please edit your question and explain why you need this. Running command1 > file; command2 < file should work out of the box. How exactly are you running the second command? – terdon Apr 3 '16 at 12:35
  • @terdon, I just updated the question as you have suggested. I hope this helps. I only need a single command in this case since the web-development server reloads on file changes. – zanona Apr 3 '16 at 12:44
15

The simplest solution is probably sponge as @heemayl suggested. Alternatively, you could do something like this:

command > tmpfile && mv tmpfile watched_file

This will cause command to save its output in tmpfile, which will only be renamed to watched_file (the file your server is set up to watch) once the command has exited and only if it has exited successfully. To also rename it on failure, use:

command > tmpfile; mv tmpfile watched_file
  • Thank you. I prefer the tmpfile method since I was looking for something that could work without dependencies. – zanona Apr 3 '16 at 12:57
  • If the command fail, an unused tmpfile will be created. To prevent that we can do something like this { command >tmpfile && mv tmpfile watched_file; } || rm tmpfile – Navid Ht Apr 5 '16 at 19:27
15

Use sponge from GNU moreutils:

echo 'a lot of content' | command 1 | sponge file.txt

Or use a temporary file.

Not the answer you're looking for? Browse other questions tagged or ask your own question.