How to run a
infinite_number_loop
in bash? , like below :for i in infinite_number_statement do date +%Y-%m-%d -d "$i day ago" 2>&1 > /dev/null if [ $? -ne 0 ] then echo $i fi done
If I run this loop in terminal in my local machine, is there any issue? (I tried a big random number range with
for
loop and got hung once.)

- 930
- 1
- 11
- 33
2 Answers
How to run a
infinite_number_loop
in bash?
The easy way: while :; do ... done
:
let i=0
while :; do
let i++
date +%Y-%m-%d -d "$i day ago" >/dev/null 2>&1 || { echo $i && exit 1; }
done
If I run this loop in terminal in my local machine, is there any issue?
Not until you realize you wasted too much time on this.

- 13,368
- 2
- 31
- 50
-
Thanks @sato , that worked. BTW something is gained every second, no regrets in "wasting" time like this ;) – prado Feb 28 '17 at 20:45
Not an infinite loop, but a better way to find the actual limit of date:
#!/bin/bash
j=$((1<<61))
i=0
while ((j>0)); do
if date +'%Y-%m-%d' -d "$((i+j)) days ago" >/dev/null 2>&1; then
((i+=j)) ; # printf 'running i %d 0x%x\n' "$i"{,}
else
((j>>=1)); # printf 'new j %d 0x%x\n' "$j"{,}
fi
((k++))
# ((k%10)) || printf 'still running %d 0x%x %d %d' "$i"{,} "$j" "$k"
done
printf "final value of limit %d 0x%x in %d loops\n" "$i"{,} "$k"
That will find the limit of date to be:
final value of limit 2147483649 0x80000001 in 64 loops
Remove the comment character # to see how that is done.
It is not a 32 bit number.
That seem to be close to a 32 bit number:
$ printf '%d\n%d\n' "$(( (1<<31) + 1 ))" "0x80000001"
2147483649
2147483649
In fact, is 2**31 + the day number of the month.
If we try with the last day in December (change line 5 in the script above):
date +'%Y-%m-%d' -d "2017-12-31 $((i+j)) days ago"
We get:
final value of limit 2147483679 0x8000001f in 68 loops
That's 31 above 2**31
:
$ printf '%d\n%d\n' "$(( (2**31) + 31 ))" "0x8000001f"
2147483679
2147483679
It is also affected by the time zone.
Arithmetic notes
The max value for a shell integer is i less than 2 raised to 63:
$ echo $(( (2**63) - 1 ))
9223372036854775807
We can get the decimal and hexadecimal representation with:
$ printf '%d %x\n' "$(( (2**63) - 1 ))"{,}
9223372036854775807 7fffffffffffffff
That's the maximum number representable in a signed integer of 64 bits (if your system is 64 bits, of course). The next number (just add one) will wrap around (overflow) to a negative number:
$ echo $(( (2**63) ))
-9223372036854775808
$ printf '%d %x\n' "$(( (2**63) ))"{,}
-9223372036854775808 8000000000000000
Which happens to be the most negative number for signed 64 bit integer.
But a faster way to get the same result is using left shift, which does the same as multiplying a number by two:
$ printf '%d %x\n' "$(( (1<<63) - 1 ))"{,}
9223372036854775807 7fffffffffffffff
yes | sed -n '='
for example – Sam Oct 03 '18 at 15:15