Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Exists a nicer way to create timestamp in front of an echo?

Currently I do it this way:

#!/bin/sh

if mount | grep -q /mnt/usb; then
        echo `date +%R\ ` "usb device already mounted"
else
        echo `date +%R\ ` "mounting usb device..."
        mount -t msdosfs /dev/da0s1 /mnt/usb

        if mount | grep -q /mnt/usb; then
                echo `date +%R\ ` "usb device successfully mounted"
        fi
fi

The output should look something like that:

10:36 usb device already mounted
share|improve this question

7 Answers 7

up vote 16 down vote accepted

You could skip the echo, and just put the message in the date command. date allows you to insert text into the format string (+%R in your example). For example:

date +"%R usb device already mounted"

You can also throw it into a shell function for convenience. For example:

echo_time() {
    date +"%R $*"
}

echo_time "usb device already mounted"

This is a cleaner if you are going to re-use it many times.

share|improve this answer
6  
echo_time will do what you expect, until your message has a % sign in it. Not a very robust solution. –  derobert Aug 29 '13 at 15:17
1  
@derobert Because the implementation is hidden away in a function, echo_time could just use the OP's date+echo construct –  Izkata Aug 29 '13 at 17:16
    
i'd just change "$*" by "$@" (to get in the habit of using the later) –  Olivier Dulac Aug 29 '13 at 17:19

You can create a variable for date +%R:

#!/bin/sh

T=$(date +%R)

if mount | grep -q /mnt/usb; then
        echo "$T usb device already mounted"
else
        echo "$T mounting usb device..."
        mount -t msdosfs /dev/da0s1 /mnt/usb

        if mount | grep -q /mnt/usb; then
                echo "$T usb device successfully mounted"
        fi
fi
share|improve this answer
3  
This is nice because it only calls date once, rather than three times. –  evilsoup Aug 29 '13 at 9:48
    
This is nice when the script does not last long, but it will have the wrong date when it will be longer. –  TaXXoR Aug 30 '13 at 5:39

With ksh93 and recent versions of bash:

ts_echo() {
  printf '%(%R)T: %s\n' -1 "$*"
}

With zsh:

ts_echo() print -P %T: "$@"

Or to avoid prompt expansion in the "$@" part:

ts_echo() echo ${(%):-%T}: "$@"

A hacky way for older versions of bash:

ts_echo() (
  PS4="\A"
  set -x; : "$@"
)

Actually, if the point is to do:

echo "<timestamp>: doing cmd args..."
cmd args...

You could do:

ts() (
  PS4='\A: doing '
  set -x; "$@"
)
ts cmd args...

Or to avoid forking a sub shell:

ts() {
  local PS4='\A: doing ' ret
  set -x; "$@"
  { ret=$?; set +x; } 2> /dev/null
  return "$ret"
}

Then:

$ ts echo whatever
14:32: doing echo whatever
whatever

(note that those are echoed on stderr, which actually may be preferable).

share|improve this answer

Here is a more robust and portable (POSIX) way to do it, particularly one that allows for % to stay unprocessed as an argument:

echo_time() {
    date +"%H:%M $(printf "%s " "$@" | sed 's/%/%%/g')"
}
share|improve this answer

When I do things like this, I usually want all lines (including any program output) to be timestamped. Thus, I'd use something like this:

#!/bin/sh

(
    if mount | grep -q /mnt/usb; then
        echo "usb device already mounted"
    else
        echo "mounting usb device..."
        mount -t msdosfs /dev/da0s1 /mnt/usb

        if mount | grep -q /mnt/usb; then
            echo "usb device successfully mounted"
        fi
    fi
) 2>&1 | perl -ne 'print "[".localtime()."] $_"'

As Stephane points out below, individual programs may buffer their output when sent to a pipe. Of course, these buffers will be flushed when the program exits so at worst the timestamps will show when the program exited (if it buffers its output and does not print enough to fill the buffer). However, the echo timestamps will all be accurate.

As a runnable sample for testing:

#!/bin/sh

(
    echo "Doing something"
    sleep 5
    echo "Doing something else..."
    ls /some/file
    sleep 8
    echo "Done."
) 2>&1 | perl -ne 'print "[".localtime()."] $_"'

Output:

[Thu Aug 29 07:32:37 2013] Doing something
[Thu Aug 29 07:32:42 2013] Doing something else...
[Thu Aug 29 07:32:42 2013] ls: cannot access /some/file: No such file or directory
[Thu Aug 29 07:32:50 2013] Done.
share|improve this answer
    
However note that once the output is going to a pipe, applications start to buffer their output, so the timings may not reflect the time they were printed. –  Stéphane Chazelas Aug 29 '13 at 12:08
2  
I suggest checking out the ts command which is part of moreutils. Its a similar perl script, but with various options for timestamp format, etc. –  derobert Aug 29 '13 at 15:18
    
@derobert - why don't you write up how to do this using ts? Seems like it would be the best option here. –  slm Aug 30 '13 at 15:29

Creating timestamps with ts

install the tool ts (part of package moreutils):

sudo apt-get install moreutils

Adding a timestamp to an output:

echo "foo" | ts

output:

Sep 03 14:51:44 foo
share|improve this answer
alias echo="d=$(date +%Y-%m-%d); echo $d "
echo hola
share|improve this answer
1  
This didn't work when I just tried it. –  slm Aug 29 '13 at 20:47
    
Just as @slm wrote. You have to protect the string from premature command and variable expansions. –  manatwork Aug 30 '13 at 15:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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