Storing timestamp of files in an array

Hi,

I have written the below script to get the timestamp of each files and result is as below

Script

find /home/user -type f -name "*.json" -printf '%Tc %p\n' | awk {'print $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7'}

Input

-rw-r--r-- 1 user domain users    17382 Jul 19 06:10 file1.json
-rw-r--r-- 1 user domain users    20463 Jul 19 06:10 file2.json
-rw-r--r-- 1 user domain users   493244 Jul 19 06:10 file3.json
-rw-r--r-- 1 user domain users    36499 Jul 19 06:10 file4.json
-rw-r--r-- 1 user domain users  2177721 Jul 19 06:13 file5.json

Output

Wed 19 Jul 2017 06:10:13 AM EDT
Wed 19 Jul 2017 06:10:13 AM EDT
Wed 19 Jul 2017 06:10:14 AM EDT
Wed 19 Jul 2017 06:10:38 AM EDT
Wed 19 Jul 2017 06:13:28 AM EDT

My requirement is store the output into an array.
ie array[1] should hold first row --> Wed 19 Jul 2017 06:10:13 AM EDT
array[2] should hold second row --> Wed 19 Jul 2017 06:10:13 AM EDT
Is it possible to store the entire output in single array through shell script

Thanks

Arrays are declared different ways in different shells. Which OS and shell are you using?

The short answer to your question is yes. If we know the shell we can give you an example.

Please find the answer
/bin/bash

GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)

CentOS Linux release 7.3.1611 (Core)
Red Hat Enterprise Linux Server release 7.0 (Maipo)
NAME="CentOS Linux"
VERSION="7 (Core)"

---------- Post updated at 09:11 AM ---------- Previous update was at 08:04 AM ----------

find /home/user -type f -name "*.json" -printf '%Tc %p\n' | awk {'print $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7'}

I'm confused. On my Ubuntu 16.04 (Xenial) system the find options you use (i.e. -printf %Tc %p\n produces

DDD dd mmm YYYY HH:MM:SS ZON /path/to/file

Seven fields. You then pipe through an awk one-liner to print the first seven fields unchanged. Yet your required output shows only the first six fields?

So it occurs to me that the following may work for you (it does on my system with bash)

IFS=! arr=( $(find . -type f -name "*.json" -printf '%Tc!' ) )

I got rid of the printing of the filepath and use an exclamation mark to separate the timestamps. IFS is similarly modified.

I hope that helps.

Andrew

---------- Post updated at 09:33 AM ---------- Previous update was at 09:21 AM ----------

Okay, after looking at the original post I realise you have an AM/PM marker which I don't. Difference in locale, I suppose. Anyway, my suggestion should still work for you.

Andrew

1 Like

This worked, thank you

Would it be safer to use stat to get a known format timestamp then convert it to one that meets your requirements rather than relying on the risks by using ls and being subject to locale etc.?

Perhaps thsi would help:-

filename=/etc/profile                  # Just as an example
E_seconds=$(stat -c %Y $filename)
timestamp=$(date -d"@$E_seconds" '+%a %d %b %Y %r %p %Z')

echo "Timestamp is \"$timestamp\" for file \"$filename\""

If you build that into a loop called in by your find, that might do it.
(converting them only to display)

As for storing the values as an array, would you be better with an associative array? Have a look at the bash manual page for a description. Basically you could then map the filename to the timestamp as a pair of items keyed by filename (timestamp may not be unique)

Moving on from that, what do you plan to do with the timestamp values? if you are looking to sort them, process them, get items based on a date range, then you would be better storing them as either seconds from the Epoch or using a format such as YYYYMoDDHHMiSS so that it makes sense to numeric comparisons.

Computer code is not easy with human format dates, so one of the above could help tremendously. If you store the value as seconds, then you can display it whenever you need to by calling the date command above.

I hope that this helps,
Robin