Wakan Tanka
Wakan Tanka

Reputation: 8042

bash appending to file inside and outside the loop

What is the difference between those two commands?

while true; do date; sleep 1; done > /tmp/log

vs

while true; do date >> /tmp/log; sleep 1; done 

Both append to file one line a time but seems that both do it different way.

I thought that first one won't append anything to file because the whole appending to file will happen after the loop ends, and because the loop is infinite nothing will ever be written to file. Also how is possible that first one is appending to file when only one > is used?

Upvotes: 3

Views: 2512

Answers (3)

Etan Reisner
Etan Reisner

Reputation: 80931

This command:

while true; do date; sleep 1; done > /tmp/log

opens the file immediately (before the loop ever even runs) (and truncates any existing content in the file) and the commands that run inside the loop inherit the open file descriptor (fd) and any output is written to that fd as the output happens.

This command:

while true; do date >> /tmp/log; sleep 1; done

opens the file once each time through the loop (immediately before running the date command). The >> operator opens the file in append mode so the existing file contents are not truncated away.

Upvotes: 1

Barmar
Barmar

Reputation: 781068

In version 1, output is added to the file immediately because the date command flushes its output when it exits, which writes everything to the standard output file.

Version 1 isn't appending to the file. It opens a file descriptor to the file when the loop starts, and empties the file when that happens. This descriptor stays open for the entire loop, and is inherited by each command in the loop as its standard output. Since it's not closed and reopened before each command, the file is not truncated each time -- they just write to the current position in the file.

Upvotes: 2

Martin Konecny
Martin Konecny

Reputation: 59611

For the first command

while true; do date; sleep 1; done

is seen as a "block". Anything that block outputs is printed to stdout. You are simply redirecting the output of that block to a file.

Imagine you had the following shell script:

#!/bin/bash
while true; do date; sleep 1; done

And now you ran

script.sh > /tmp/log

You would also expect the log file to be continuously written to.

Upvotes: 2

Related Questions