2

With the following bash script:

#!/bin/bash
let SECONDS=5

until [[ "$SECONDS" -le "1" ]]; do
    echo SECONDS $SECONDS
    (( SECONDS -= 1 ))

#    sleep 1
done

I am seeing strange behavior. Namely, that if I uncomment the sleep 1 the loop continues but the counter does not decrement, I see output like:

$./mvce.sh 
SECONDS 5
SECONDS 5
SECONDS 5
SECONDS 5
SECONDS 5
SECONDS 5
SECONDS 5

Removing that line results in the expected:

$./mvce.sh 
SECONDS 5
SECONDS 4
SECONDS 3
SECONDS 2

I'm not really sure why this is happening. I can rename the variable to something else and things work as expected so it seems that something about sleep breaks my SECONDS variable.

This was surprising, why does calling sleep override the SECONDS variable within my script?

Cyrus
  • 84,225
  • 14
  • 89
  • 153
enderland
  • 13,825
  • 17
  • 98
  • 152
  • 3
    `SECONDS` is a special/reserved shell variable and shouldn't be used in user applications – Inian Mar 30 '18 at 14:45
  • See paragraph 4 of http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html -- all-caps names are used for variables meaningful to the shell and POSIX-specified tools; lowercase names are reserved for application-defined use. – Charles Duffy Mar 30 '18 at 14:46
  • @CharlesDuffy can you post that as an answer, that's basically what I was looking for here! – enderland Mar 30 '18 at 14:51
  • ...frankly, it looks to me like @anubhava has written a pretty good answer -- if you want to let them know what part of the question they aren't covering that I touch on in my comment above (maybe the link into the POSIX spec?), letting them update their question to cover it probably makes as much sense as adding something that would be mostly-duplicative. – Charles Duffy Mar 30 '18 at 15:31
  • Possible duplicate of [Save in a variable the number of seconds a process took to run](https://stackoverflow.com/questions/858594/save-in-a-variable-the-number-of-seconds-a-process-took-to-run) – jww Mar 30 '18 at 17:02

1 Answers1

6

SECONDS is reserved variable in shell. That's why you must always use lowercase or mixed case variables in your script and avoid using all uppercase variable names.

#!/bin/bash
let secs=5

until [[ "$secs" -le "1" ]]; do
    echo SECONDS $secs
    (( secs -= 1 ))

   sleep 1
done

That gives expected output:

SECONDS 5
SECONDS 4
SECONDS 3
SECONDS 2

Doumentation:

SECONDS
Each time this parameter is referenced, the number of seconds since shell invocation is returned. If a value is assigned to SECONDS, the value returned upon subsequent references is the number of seconds since the assignment plus the value assigned. If SECONDS is unset, it loses its special properties, even if it is subsequently reset.

anubhava
  • 761,203
  • 64
  • 569
  • 643