Haravikk
Haravikk

Reputation: 3290

Best Way to Get File Modified Time in Seconds

This seems to be a classic case of non-standard features on various platforms.

Quite simply, I want a universally (or at least widely) supported method for getting the modified time of a file as a unix timestamp in seconds.

Now I know of various ways to do this with stat but most are platform specific; for example stat -c %Y $file works for some, but won't work on OS X (and presumably other FreeBSD systems) which uses stat -f %m $file instead.

Likewise, some platforms support date -r $file +%s, however OS X/FreeBSD again does not as the -r option seems to just be an alternate to using +%s for getting a unix timestamp, rather than the reference file option as on other platforms.

The other alternative I'm familiar with is to use find with the -printf option, but again this is not widely supported. The last method I know of is parsing ls which, aside from being an unpleasant thing to have to do, is not something I believe can (or at least should) be relied upon either.

So, is there a more compatible method for getting a file's modified time? Currently I'm just throwing different variations of stat into a script and running them until one exits with a status of zero, but this is far from ideal, even if I cache the successful command to run first in future.

Upvotes: 9

Views: 5442

Answers (3)

Haravikk
Haravikk

Reputation: 3290

Since it seems like there might not be a "correct" solution I figured I'd post my current one for comparison:

if stat -c %Y . >/dev/null 2>&1; then
    get_modified_time() { stat -c %Y "$1" 2>/dev/null; }
elif stat -f %m . >/dev/null 2>&1; then
    get_modified_time() { stat -f %m "$1" 2>/dev/null; }
elif date -r . +%s >/dev/null 2>&1; then
    get_modified_time() { date -r "$1" +%s 2>/dev/null; }
else
    echo 'get_modified_time() is unsupported' >&2
    get_modified_time() { printf '%s' 0; }
fi

[edit] I'm updating this to reflect the more up to date version of the code I use, basically it tests the two main stat methods and a somewhat common date method in any attempt to get the modified time for the current working directory, and if one of the methods succeeds it creates a function encapsulating it for use later in the script.

This method differs from the previous one I posted since it always does some processing, even if get_modified_time is never called, but it's more efficiently overall if you do need to call it most of the time. It also lets you catch an unsupported platform earlier on.

If you prefer the function that only tests functions when it is called, then here's the other form:

get_modified_time() {
    modified_time=$(stat -c %Y "$1" 2> /dev/null)
    if [ "$?" -ne 0 ]; then
        modified_time=$(stat -f %m "$1" 2> /dev/null)
        if [ "$?" -ne 0 ]; then
            modified_time=$(date -r "$1" +%s 2> /dev/null)
            [ "$?" -ne 0 ] && modified_time=0
        fi
    fi
    echo "$modified_time"
}

Upvotes: 8

Das_Sams
Das_Sams

Reputation: 11

Why so complicated?

after not finding something on the web I simply read the manual of ls

man ls

which gave me

ls --time-style=full-iso -l

and change time in the format hh:mm:ss.sssssssss As

ls --time-style=+FORMAT -l

while FORMAT is used like with date (see man date)

ls --time-style=+%c

will give you local date and time with seconds as an integer (without decimal point). You can strip off additional ls information (e.g. file name, owner...) when you pipe through awk.

Upvotes: 1

John Zwinck
John Zwinck

Reputation: 249394

Just ask the operating system for its name, and go from there. Alternatively, write a C program, or use Python or something else that's pretty common and more standardized: How to get file creation & modification date/times in Python?

Upvotes: 0

Related Questions