9

Problem: I need to check if today is Thursday and perform different actions based on the result of this condition. I tried two different approaches:

Getting the Day Name:

DAYOFWEEK=$(date +"%a")
echo DAYOFWEEK: $DAYOFWEEK
if ["$DAYOFWEEK" == "Thu"]; 
then   
   echo YES
else
    echo NO
fi

Getting the Day Num:

DAYOFWEEK=$(date +"%u")
echo DAYOFWEEK: $DAYOFWEEK

if ["$DAYOFWEEK" == 4]; 
then
   echo YES
else
   echo NO
fi

In both cases, the output is NO, even though it should be YES. What is wrong?

  • 1
    A side note: those ; would be required if you would have then in the same line with if. In this case they are redundant. – manatwork Mar 7 '13 at 12:40
11

The problem is the missing blank.

The following code will work in shells whose [ builtin command accepts == as an alias for =:

if [ "$DAYOFWEEK" == 4 ];  then    echo YES; else    echo NO; fi

But keep in mind (see help test in bash):

  • == is not officially mentioned, you should use = for string compare
  • -eq is intended for decimal arithmetic tests (won't make a difference here for date +%u but would for date +%d for instance when it comes to comparing 04 and 4 which are numerically the same but lexically different).

I would prefer:

 if [ "${DAYOFWEEK}" -eq 4 ];  then    echo YES; else    echo NO; fi

Generally you should prefer the day number approach, because it has less dependency to the current locale. On my system the output of date +"%a" is today Do.

3

Don't overlook case which is often a better way to do this kind of things:

Also beware that the output of date +%a is locale-dependent, so if you expect the English names, your script will stop working when invoked by a French or Korean user for instance.

case $(LC_ALL=C date +%a) in
   (Mon) echo first day of the week;;
   (Thu) do-something;;
   (Sat|Sun) echo week-end;;
   (*) echo any other day;; # last ;; not necessary but doesn't harm
esac

Note that above is one of the rare cases where that $(...) doesn't need to be quoted (though quotes won't harm. Same as in var="$(...)").

0

In the same idea, I use the following piece of code to "disable" a cron before a chosen hour
Of course, I would rather modify the crontab itself... if I were granted the necessary rights to :)

Here's a simple test which aborts a bash script unless we're at night.

# Delay or restrict execution.
# Here, we quit unless hour is greater than (gt) 2 and (-a) lower than (lt) 7
# i.e. execution happens only at 3,4,5&6 o'clock.
if  /usr/bin/test `date '+%H'` -gt 2 -a `date '+%H'` -lt 7; then
  echo LETS_START_PROCESSING;
else
  exit;
fi

#Put job here
  • Why use /usr/bin/test instead of the shell's builtin [ command? – Stéphane Chazelas Nov 22 '17 at 15:01
  • @Stéphane Chazelas I didn't use 3,4,5,6 because I don't have access to the crontab. (this is the 2nd line of my post :) Our servers are managed by Claranet, and we already lost a week of ticket-ping-pong to get... a working cron (not kidding). So we avoid messing up and re-opening tickets when we can :) For that reason, we asked for an hourly cron task instead of daily, and until all our tests are done, it will be way easier not to touch the task, and add our controls in the executed script. – Balmipour Nov 22 '17 at 15:56
  • Ah OK, sorry, I thought you meant you didn't have the right to modify the cron executable as opposed to the user's crontab. – Stéphane Chazelas Nov 22 '17 at 16:01
  • @Stéphane Chazelas About the test syntax, I preferred it over [] or [[]] because I tried my script on some other server first, where I could use the crontab. After too many surprises with crons, I got the habit to use absolute path in crontabs as much as possible. One may say it makes tests ugly, and will be right... but I'll answer that shell test are always ugly anyway, and will be right too ^^ What matters to me was mostly to have an answer which would work with a simple copy/paste, and include some explainations. – Balmipour Nov 22 '17 at 16:02
  • 1
    Note that -a is deprecated in test. Standardly, you'd use: hour=$(date +%H); if [ "$hour" -gt 2 ] && [ "$hour" -lt 7 ] (or hour=`date +%H` if you needed to be compatible to the Bourne shell, that is Solaris 10 and older and maybe some rare SCO unices nowadays) – Stéphane Chazelas Nov 22 '17 at 16:11
0

To stop the script in day of week, only delete the line of the day:

DAYOFWEEK=$(date +"%u")
echo "$DAYOFWEEK";
if [ "$DAYOFWEEK" == 1 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 2 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 3 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 4 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 5 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 6 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 7 ]; then exit; else echo; fi
  • Welcome on the Unix SE! I am not sure if I understood your first line correctly. Wouldn't be an if [ "$DAYOFWEEK" -lt 7 ] better? – peterh May 21 '18 at 19:10
-1

Firstly you should quote the assignment DAYOFWEEK="$(date +%u)"

And you need to have spaces on each side of the [ and ] brackets.

The semi-colon at the end of the line is redundant.

  • 1
    The quoting is not needed. – H.-Dirk Schmitt Mar 7 '13 at 14:51
  • To expand on @H.-DirkSchmitt's comment: the reason why the quoting is not needed is that the output will not contain any spaces. – a CVn Mar 7 '13 at 15:07
  • @MichaelKjörling: No - it is never needed ;-) Try the example: a=$(echo 1 2 3); echo $a; – H.-Dirk Schmitt Mar 7 '13 at 15:45
  • @H.-DirkSchmitt a=$(echo "1 2 3"); echo $a with multiple spaces between the digits (StackExchange won't let me make it a simple copy-and-paste, unfortunately). – a CVn Mar 7 '13 at 15:54
  • @MichaelKjörling - see man bash "If the substitution appears within double quotes, word splitting and pathname expansion are not performed on the results." So it makes in the case of the question and the "1 2 3" example no difference. – H.-Dirk Schmitt Mar 7 '13 at 16:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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