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.
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"
}