Put a text in front of every new line that a program prints to stdout

So I want to do some logging and therefor, want to put a date in front of a bash script's output. The problem is that is has multiple lines of output. I am able to only put the date before the whole output. But then I have a line without a date in the logs. Of course I can assume the date from the line above is the same, but I was hoping there is a solution. Thanks in advance!

This is my script that calls another script:

#!/bin/sh
echo $(date "+%F %T") : starting script
echo $(date "+%F %T") : $(./script.sh)
echo $(date "+%F %T") :script ended

This is the output:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
second line of output
2012-07-26 15:35:17 : script ended

And thats what I would like to have:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
2012-07-26 15:35:15 : second line of output
2012-07-26 15:35:17 : script ended

Solution 1:

According to a similar question on Stack Overflow, there are 2 great options.

awk (Answer)

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

annotate (Answer)

annotate is a small bash script, that can either be directly obtained through the link provided here, or, on Debian based systems, through the package devscripts (in the form of annotate-output).

Solution 2:

I think that you can use awk for this:

./script.sh | awk '{ print strftime()" : "$0; }'

(see http://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html for formatting the date returned by strftime())

Solution 3:

You can use awk

./script.sh | awk '{ print d,$1}' "d=$(date "+%F %T")"

awk takes an input stream and modifies it's output. This script is saying "print d followed by the original output", then then populates d with the date.

Solution 4:

This will print the current date and time before each line of output of ./script.sh:

set -f
./script.sh | while read -r LINE; do echo $(date "+%F %T") : "$LINE"; done
set +f

How it works

  • set -f turns off bash expansion (or echo * wouldn't print an actual asterisk).

  • while read -r LINE; do ... done saves one line of output in the variable $LINE and executes ..., until all lines are processed.

  • echo $(date "+%F %T") : "$LINE" prints the line with the current time and date.

  • set +f turns bash expansion back on, so it won't interfere with the rest of your bash script.