3

I want to generate a series of timestamp and compare with the max limit. I wanted to use the while loop to check this.

Here is my code.

start_ts='2021-08-07 15:00:00'
end_ts='2021-08-10 05:00:00'

while [ "$start_ts" > "$end_ts" ] do echo $start_ts start_ts=$(date -ud "$start_ts +0 + 30 minutes" +'%Y-%m-%d %H:%M:%S') done

But this loop is going and going, not stopping at $end_ts value.

Am I missing something?

1 Answers1

8

When used with [ ... ], the unquoted > is a redirection operator. This means that you now probably have a file named 2021-08-10 05:00:00 in your current directory, created by redirecting the output of the [ command to file.

The command

[ "$start_ts" > "$end_ts" ]

may also be written

[ "$start_ts" ] >"$end_ts"

(see e.g. How is this command legal? "> file1 < file2 cat"). This is a test for whether the string "$start_ts" is non-empty, and the output of that test (which is nothing because [ does not output anything) is redirected to the file $end_ts.

When used with [[ ... ]], the > is a string comparison operator that tests whether two strings are sorted in a particular way. This is likely what you want to use, but to get the logic right you'd use <, or swap the arguments around >, or use until instead of while.


Another approach would be to skip the string comparisons completely and instead use integer comparisons of Unix timestamps:

start_ts=$( date -d '2021-08-07 15:00:00' +%s )
end_ts=$( date -d '2021-08-10 05:00:00' +%s )

while [ "$start_ts" -lt "$end_ts" ]; do printf '%(%Y-%m-%d %H:%M:%S)T\n' "$start_ts" start_ts=$(( start_ts + 1800 )) done

Since there is no call to GNU date inside the loop, this runs many times faster than the original code (about 50 times faster on my system).

Kusalananda
  • 333,661
  • Or they could use [ "$start_ts" '>' "$end_ts" ]. > is not a standard [ operator, but many implementations support it as an extension, including (but not limited to) the [ builtin of those shells that support the [[...]] ksh-style construct. POSIXly, you can use expr instead of [/test. – Stéphane Chazelas Aug 11 '21 at 09:03
  • Why not use -gt instead? That works with single brackets. – user000001 Aug 11 '21 at 19:25
  • 1
    @user000001 They are comparing strings. -gt requires two integers. But yes, if they formatted their timestamps as Unix timestamps with %s, it would be appropriate to use -gt or -lt. – Kusalananda Aug 11 '21 at 19:26
  • @Kusalananda: Right, that's a good point, thanks. – user000001 Aug 11 '21 at 19:34
  • 1
    @user000001 Thanks for the input! See updated answer. – Kusalananda Aug 11 '21 at 19:45