Steph Locke
Steph Locke

Reputation: 6146

Bash convert a number of epoch values to datetime

I have a number of files in the form foo_[SECONDS.MILLISECONDS]_bar.tar.gz and for each file I would like to be to get a datetime value (YYYYMMDDHHMMSS) for each file.

So far I have

ls -1 /filestore/*.tar.gz | cut -d _ -f 2  | date -f -

But this errors along the lines of

date: invalid date '1467535262.712041352'

How should a bash pipeline of epoch values be converted into a datetime string?

MWE

mkdir tmpBLAH
touch tmpBLAH/foo_1467483118.640314986_bar.tar.gz
touch tmpBLAH/foo_1467535262.712041352_bar.tar.gz
ls -1 tmpBLAH/*.tar.gz | cut -d _ -f 2 | date -f -

Upvotes: 4

Views: 6327

Answers (4)

λuser
λuser

Reputation: 1001

First, the -1 option to ls is useless, because ls prints its output one file per line by default, it's just that when the output is a terminal (not a pipe), it pretty-prints in columns. You can check that fact by just running ls | cat.

Then, date converts epoch timestamps safely only if prefixed with an @.

% date -d 0
Sun Jul  3 00:00:00 CEST 2016
% LANG=C date -d @0
Thu Jan  1 01:00:00 CET 1970

% date -d 12345
date: invalid date '12345'
% date -d @12345
Thu Jan  1 04:25:45 CET 1970

Which gives:

printf "%s\n" tmpBLAH/foo_*_bar.tar.gz | sed 's/.*foo_/@/; s/_bar.*//' | date -f -

Upvotes: 3

gzh
gzh

Reputation: 3596

To convert epoch time to datetimem, please try the following command:

    date -d  @1346338800 +'%Y%m%d%H%M%S'

1346338800 is a epoch time.

About your case, for comand line as following:

echo 1467535262.712041352 | cut -d '.' -f 1 | xargs -I{} date -d @{} +'%Y%m%d%H%M%S'

you will get:

20160703174102

Upvotes: 4

tripleee
tripleee

Reputation: 189457

Something like this?

for f in /filestore/*.tar.gz; do
    epoch=${f#*_}
    date -d @${epoch%%.*} +%Y%m%d%H%M%S
done

The syntax of the date command differs between platforms; I have assumed GNU date, as commonly found on Linux. (You could probably use date -f if you add the @ before each timestamp, but I am not in a place where I can test this right now.) Running a loop makes some things easier, such as printing both the input file name and the converted date, while otherwise a pipeline would be the most efficient and idiomatic solution.

As an aside, basically never use ls in scripts.

Upvotes: 3

heemayl
heemayl

Reputation: 42017

You can do:

for i in foo_*_bar.tar.gz; do date -d "@$(cut -d_ -f2 <<<"$i")" '+%Y%m%d%H%M%S'; done

The epoch time is provided with the -d @<time> and the desired format is '+%Y%m%d%H%M%S'.

Example:

% for i in foo_*_bar.tar.gz; do date -d "@$(cut -d_ -f2 <<<"$i")" '+%Y%m%d%H%M%S'; done
20160703001158
20160703144102

Upvotes: 0

Related Questions