How can I detect BSD vs. GNU version of date in shell script

You want to detect what version of the date command you're using, not necessarily the OS version.

The GNU Coreutils date command accepts the --version option; other versions do not:

if date --version >/dev/null 2>&1 ; then
    echo Using GNU date
else
    echo Not using GNU date
fi

But as William Pursell suggests, if at all possible you should just use functionality common to both.

(I think the options available for GNU date are pretty much a superset of those available for the BSD version; if that's the case, then code that assumes the BSD version should work with the GNU version.)


It is recommended to use feature-based defection rather than the os-based or platform-based detection.

Following sample code show how it works:

if is-compatible-date-v; then
    date -v -1d
elif is-compatible-date-d; then
    date --date="1 day ago"
fi
function is-compatible () {
    "$@" >/dev/null 2>&1
}

function is-compatible-date-v () {
    is-compatible date -v +1S
}

function is-compatible-date-d () {
    is-compatible date -d '1 second'
}

I was having the exact need to writing some shellcode to deal with date, and hoping the code be able to run on both BSD and GNU version of date.

I end up with a set of scripts that provides a uniform interface for both BSD and GNU version of date.

Example:

Follow command will output a date that is 21 days later than 2008-10-10, and it works with both BSD and GNU version of date.

$ xsh x/date/adjust +21d 2008-10-10
2008-10-31

The scripts can be found at:

  • https://github.com/xsh-lib/core/tree/master/functions/date

It's a part of a library called xsh-lib/core. To use them you need both repos xsh and xsh-lib/core, I list them below:

  • https://github.com/alexzhangs/xsh

  • https://github.com/xsh-lib/core

Hope this will help people with the same need.


Use portable flags. The standard is available here

For the particular problem of printing a relative date, it is probably easier to use perl than date:

perl -E 'say scalar localtime(time - 86400)'

(note that this solution utterly fails on 23 or 25 hour days, but many perl solutions are available to address that problem. See the perl faq.)

but you could certainly use a variation of Keith's idea and do:

if date -v -1d > /dev/null 2>&1; then
  DATE='date -v -1d'
else
  DATE='date --date="1 day ago"'
fi
eval "$DATE"

or just

DATE=$(date -v -1d 2> /dev/null) || DATE=$(date --date="1 day ago")

Another idea is to define a function to use:

if date -v -1d > /dev/null 2>&1; then
    date1d() { date -v -1d; }
else
    date1d() { date --date='1 day ago'; }
fi

Tags:

Shell

Date

Gnu

Bsd