I'm working with a bash script which polls build progress from several different systems. If a build is complete, it stats a log file to find out the last time it was edited, then feeds that time into date to produce human-readable output of when the build completed.

Because this is being run on some different systems, we have output that looks like:

sys00 finished around:        2015-06-11 01:42:29.484345955 -0700
sys01 finished around:        2015-06-11 01:21:17.560101447 -0700
sys02 finished around:        2015-06-11 03:51:56 -0700
sys03 finished around:        2015-06-11 04:32:12 -0700
sys04 finished around:        2015-06-11 01:40:47.977893386 -0700
sys05 finished around:        2015-06-11 01:16:12.158137851 -0700

My priority is making these look the same, and since I don't need the extra precision from the first and final two systems, I just want to chop that off. I've been attempting to do this with awk:

echo $TIME | awk '[0-9]{9} {gsub('', '[0-9]{9}')}' -

but have had little success. I'm not familiar enough with sed to decide whether it would be a more appropriate tool here. And I'm not sure if date can be instructed to leave it off. Here's the date command I'm using currently:

COMMAND='date -r `stat -f "%m" '"$BASENAME"'/../logs/catTest*.log |& head -n1` +"%Y-%m-%d %H:%M:%S %z"'

(Where $BASENAME is the base path we use to find the log file.)

How can I get rid of those pesky digits after the period?

  • What systems are you running those date commands on? At least GNU date (coreutils) prints just the seconds (00..59) without nanoseconds. Does the standard date -R output fulfil your needs? – Lekensteyn Jun 11 '15 at 21:53
  • Can you post your desired output? – ayrton_senna Jun 11 '15 at 21:56
  • These commands are being run on four Fedora systems (top 2/bottom 2) and two OSX systems (sys02, 10.6; sys03, 10.8). Desired output is similar to what you suggested, ayrton_senna, although if possible I'd like to keep the -0700 (adding it back on manually is fine) – ssonicblue Jun 11 '15 at 22:07
  • @ssonicblue i have suggested a second way of doing it. did you check it? – ayrton_senna Jun 11 '15 at 22:41

for a sed answer, you could use this to filter out the decimals :

sed 's/\.[0-9]\{1,\}//'

How it works :

  • \. will match a literal .
  • [0-9]\{1,\} will match one or more digits

The resulting pattern means "match a literal . followed by one or more digits" and replaces this with nothing.

| improve this answer | |
  • I didn't realize sed's regex syntax was so similar to vim's. This works perfectly, thank you. – ssonicblue Jun 11 '15 at 22:10
  • 1
    @ssonicblue, all regular expressions are derived from ed, specifically in this case ed had two children, sed and vi. And vi, begot nvi and vim, and had other children. And sed begot grep and awk, and had other children. and awk begot perl which begot CGI.pm which begot many flamewars. – hildred Jun 11 '15 at 22:45

If i usderstand your question correctly. Your desired output is


sys00 finished around: 2015-06-11 01:42:29 sys01 finished around: 2015-06-11 01:21:17 sys02 finished around: 2015-06-11 03:51:56 sys03 finished around: 2015-06-11 04:32:12 sys04 finished around: 2015-06-11 01:40:47 sys05 finished around: 2015-06-11 01:16:12

use field seperator of awk

awk -F. '{print $1}' inputfile.txt | awk -F- '{print $1, $2, $3}'

If you want output like this out2.txt

sys00 finished around: 2015 06 11 01:42:29 -0700 sys01 finished around: 2015 06 11 01:21:17 -0700 sys02 finished around: 2015 06 11 03:51:56 -0700 sys03 finished around: 2015 06 11 04:32:12 -0700 sys04 finished around: 2015 06 11 01:40:47 -0700 sys05 finished around: 2015 06 11 01:16:12 -0700

awk -F. '{print $1}' tst.txt | awk -F- '{print $1, $2, $3, "-0700"}'

| improve this answer | |

I'm surprised you got anything given that stat -f "%m" ... is not valid. Are you sure you copied the current version of your command?

It looks like you are using -c (specify format) not -f (filesystem) you you get the mountpoint for the list of files you provide to stat, which you then truncate to a single path and then have date stat the mountpoint and provide a format.

there are several things you can do to speed up or simplify the first of which is to not use date.

COMMAND='stat -fc "%y" '"$BASENAME"'/../logs/catTest*.log |& head -n1'

this unfortunately is locale dependant and includes nanoseconds, so we can use

COMMAND='LC_ALL=C stat -fc "%y" '"$BASENAME"'/../logs/catTest*.log |& head -n1|sed "s/\.[0-9]\+//"'

A second option is to not have date call stat

COMMAND='date `stat -fc "@%Y" '"$BASENAME"'/../logs/catTest*.log |& head -n1` +"%Y-%m-%d %H:%M:%S %z"'

If this still displays nanoseconds (which it should not, file a bugreport) you can filter with a simpler regular expression.

COMMAND='date `stat -fc "@%Y" '"$BASENAME"'/../logs/catTest*.log |& head -n1` +"%Y-%m-%d %H:%M:%S %z"|sed "s/\.0\+//"'

There is one more thing that could possibly speed things up (depending if it is quicker to stat all the log files or spawn another task) and that is to filter the files before stat

COMMAND='ls "$BASENAME"'/../logs/catTest*.log|head -n1|LC_ALL=C xargs stat -fc "%y" |sed "s/.[0-9]+//'

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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