Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How to compare two dates in a shell script?

For example something like


if [ $todate -ge $cond ];

It doesn't work. How can I achieve the desired result?

share|improve this question
What do you want to loop for? Do you mean conditional rather than loop? – Mat Jul 25 '13 at 7:46
Why you tagged files? Are those dates actually file times? – manatwork Jul 25 '13 at 7:47
Check out this on stackoverflow: stackoverflow.com/questions/8116503/… – slm Jul 25 '13 at 14:04

The right answer is still missing:

todate=$(date -d 2013-07-18 +%s)
cond=$(date -d 2014-08-19 +%s)

if [ $todate -ge $cond ];
share|improve this answer
Donno why someone downvoted this, it's pretty accurate and doesn't deal with concatenating ugly strings. Convert your date to unix timestamp (in seconds), compare unix timestamps. – Nicholi May 2 '15 at 23:16

You are missing the date format for the comparison:


todate=$(date -d 2013-07-18 +"%Y%m%d")  # = 20130718
cond=$(date -d 2013-07-15 +"%Y%m%d")    # = 20130715

if [ $todate -ge $cond ]; #put the loop where you need it
 echo 'yes';

You are missing looping structures too, how are you planning to get more dates?

share|improve this answer

This is not a problem of looping structures but of data types.

Those dates (todate and cond) are strings, not numbers, so you cannot use the "-ge" operator of test. (Remember that square bracket notation is equivalent to the command test.)

What you can do is use a different notation for your dates so that they are integers. For example:

date +%Y%m%d

will produce an integer like 20130715 for July 15th, 2013. Then you can compare your dates with "-ge" and equivalent operators.

enter code here

Update: if your dates are given (e.g. you are reading them from a file in 2013-07-13 format) then you can preprocess them easily with tr.

$ echo "2013-07-15" | tr -d "-"
share|improve this answer

Can use a standard string comparison to compare the chronological ordering [of strings in a year, month, day format].


if [[ "$date_a" > "$date_b" ]] ;
    echo "break"

Thankfully, when [strings that use the YYYY-MM-DD format] are sorted* in alphabetical order, they are also sorted* in chronological order.

(* - sorted or compared)

Nothing fancy needed in this case. yay!

Cheers, -David

share|improve this answer

The operator -ge only works with integers, which your dates aren't.

If your script is a bash or ksh or zsh script, you can use the < operator instead. This operator is not available in dash or other shells that don't go much beyond the POSIX standard.

if [[ $cond < $todate ]]; then break; fi

In any shell, you can convert the strings to numbers while respecting the order of dates simply by removing the dashes.

if [ "$(echo "$todate" | tr -d -)" -ge "$(echo "$cond" | tr -d -)" ]; then break; fi

Alternatively, you can go traditional and use the expr utility.

if expr "$todate" ">=" "$cond" > /dev/null; then break; fi

As invoking subprocesses in a loop can be slow, you may prefer to do the transformation using shell string processing constructs.

todate_num=${todate%%-*}${todate#*-}; todate_num=${todate_num%%-*}${todate_num#*-}
cond_num=${cond%%-*}${cond#*-}; cond_num=${cond_num%%-*}${cond_num#*-}
if [ "$todate_num" -ge "$cond_num" ]; then break; fi

Of course, if you can retrieve the dates without the hyphens in the first place, you'll be able to compare them with -ge.

share|improve this answer

I convert the Strings into unix-timestamps (seconds since 1.1.1970 0:0:0). These can compared easily

unix_todate=$(date -d "${todate}" "+%s")
unix_cond=$(date -d "${cond}" "+%s")
if [ ${unix_todate} -ge ${unix_cond} ]; then
   echo "over condition"
share|improve this answer

dates are strings, not integers; you can't compare them with standard arithmetic operators.

one approach you can use, if the separator is guaranteed to be -:

read -ra todate <<<"$todate"
read -ra cond <<<"$cond"
for ((idx=0;idx<=numfields;idx++)); do
  (( todate[idx] > cond[idx] )) && break
unset IFS

This works as far back as bash 2.05b.0(1)-release.

share|improve this answer

There is also this method from the article titled: Simple date and time calulation in BASH from unix.com.

These functions are an excerpt from a script in that thread!

date2stamp () {
    date --utc --date "$1" +%s

dateDiff (){
    case $1 in
        -s)   sec=1;      shift;;
        -m)   sec=60;     shift;;
        -h)   sec=3600;   shift;;
        -d)   sec=86400;  shift;;
        *)    sec=86400;;
    dte1=$(date2stamp $1)
    dte2=$(date2stamp $2)
    if ((diffSec < 0)); then abs=-1; else abs=1; fi
    echo $((diffSec/sec*abs))


# calculate the number of days between 2 dates
    # -s in sec. | -m in min. | -h in hours  | -d in days (default)
    dateDiff -s "2006-10-01" "2006-10-32"
    dateDiff -m "2006-10-01" "2006-10-32"
    dateDiff -h "2006-10-01" "2006-10-32"
    dateDiff -d "2006-10-01" "2006-10-32"
    dateDiff  "2006-10-01" "2006-10-32"
share|improve this answer

You can also use mysql's builtin function to compare the dates. It gives the result in 'days'.

diff=$(mysql -u${DBUSER} -p${DBPASSWORD} -N -e"SELECT DATEDIFF('${date_today}','${from_date}');")

Just insert the values of $DBUSER and $DBPASSWORD variables according to yours.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.