#!/bin/bash
clear
echo "Wishing according to Time of the PC"
h=$(date '+%H') #This line works, I've Checked.
if test $h -gt 6 -a $h -lt 12
then
echo "Good Morning"
elif test $h -gt 12 -a $h -lt 16
then
echo "Good Afternoon"
elif test $h -gt 16 -a $h -lt 20
then
echo "Good Evening"
else
echo "Good Night"
fi
Output should be coming according to My PC's time which is 4:00 PM but the above code isn't executing that if and elif conditions (I mean, if and elif are always returning false) and is directly jumping to else part. I am using Linux 7.9. I tried using nested if as well but it returns false always as well.
you're not capturing when $h is 16
only when it's less or more
see -ge (greater than or equal to) in the below
allow me to make this more idiomatic (use of test is not current practice, use [[ ... ]]):
h=$(date '+%H')
h=${h#0} # remove leading zero
if [[ $h -gt 6 && $h -lt 12 ]]
then
echo "Good Morning"
elif [[ $h -ge 12 && $h -lt 16 ]]
then
echo "Good Afternoon"
elif [[ $h -ge 16 && $h -lt 20 ]]
then
echo "Good Evening"
else
echo "Good Night"
fi
note that I remove any leading zero,
this is because a leading zero can make a number (e.g. 09)
interpreted as an octal, which is not what you want!
Related
my case is very simple:
I am trying to compare two values:
a=0.2
b=0.1
The code that I am trying to execute is:
if [ "$a" -gt "$b" ]; then
echo "You are running an outdated version"
fi
Assuming you want to compare version numbers, would you please try the following:
#!/bin/bash -posix
# compares version numbers
# prints 0 if $a == $b
# positive number if $a is newer than $b
# negative number if $a is older than $b
vercmp() {
local a=$1
local b=$2
local a1=${a%%.*} # major number of $a
local b1=${b%%.*} # major number of $b
if [[ $a = "" ]]; then
if [[ $b = "" ]]; then
echo 0 # both $a and $b are empty
else
vercmp "0" "$b"
fi
elif [[ $b = "" ]]; then
vercmp "$a" "0"
elif (( 10#$a1 == 10#$b1 )); then
local a2=${a#*.} # numbers after the 1st dot
if [[ $a2 = $a ]]; then
a2="" # no more version numbers
fi
local b2=${b#*.} # numbers after the 1st dot
if [[ $b2 = $b ]]; then
b2="" # no more version numbers
fi
vercmp "$a2" "$b2"
else
echo $(( 10#$a1 - 10#$b1 ))
fi
}
Examples:
vercmp 0.2 0.1
=> 1 (positive number: the former is newer)
vercmp 1.0.2 1.0.10
=> -8 (negative number: the latter is newer)
a=0.2
b=0.1
if (( $(vercmp "$a" "$b") > 0 )); then
echo "You are running an outdated version"
fi
Here is my code
CURR_MNTH=$(date +'%m' -d 'now')
if [$CURR_MNTH < 04]
THIS_QTR=1
elif [$CURR_MNTH < 07] && [$CURR_MNTH > 03]
THIS_QTR=2
elif [$CURR_MNTH < 10] && [$CURR_MNTH > 07]
THIS_QTR=3
elif [$CURR_MNTH > 09]
THIS_QTR=4
fi
echo $THIS_QTR
I am trying to get the current quarter with the above logic, but the prompt says that i have `elif' unexpected error.. Can someone please help me
Provided that you use Bash, there are numerous errors:
no semicolons after the if statements;
no spaces between brackets and conditional expressions;
conjunctions should be given inside the same set of brackets;
consider using -lt and -gt for value tests.
The correct code would look like this:
CURR_MNTH=$(date +'%m' -d 'now')
if [[ $CURR_MNTH -lt 4 ]]; then
THIS_QTR=1
elif [[ $CURR_MNTH -lt 7 && $CURR_MNTH -gt 3 ]]; then
THIS_QTR=2
elif [[ $CURR_MNTH -lt 10 && $CURR_MNTH -gt 7 ]]; then
THIS_QTR=3
elif [[ $CURR_MNTH -gt 9 ]]; then
THIS_QTR=4
fi
echo $THIS_QTR
Consider running http://www.shellcheck.net/ on your code next time.
You can get the quarter from the month by a formula:
THIS_QTR=$(( 1 + (10#$CURR_MNTH - 1) / 3))
The 10# prefix indicates decimal number, thus preventing the leading 0 to be interpreted as octal number indicator.
In the following code I want to compare the command line arguments with the parameters but I am not sure what is the current syntax to compare the arguments with parameters..i.e "==" or "-eq".
#!/bin/bash
argLength=$#
#echo "arg = $1"
if [ argLength==0 ]; then
#Running for the very first
#Get the connected device ids and save it in an array
N=0
CONNECTED_DEVICES=$(adb devices | grep -o '\b[A-Za-z0-9]\{8,\}\b'|sed -n '2,$p')
NO_OF_DEVICES=$(echo "$CONNECTED_DEVICES" | wc -l)
for CONNECTED_DEVICE in $CONNECTED_DEVICES ; do
DEVICE_IDS[$N]="$CONNECTED_DEVICE"
echo "DEVICE_IDS[$N]= $CONNECTED_DEVICE"
let "N= $N + 1"
done
for SEND_DEVICE_ID in ${DEVICE_IDS[#]} ; do
callCloneBuildInstall $SEND_DEVICE_ID
done
elif [ "$1" -eq -b ]; then
if [ $5 -eq pass ]; then
DEVICE_ID=$3
./MonkeyTests.sh -d $DEVICE_ID
else
sleep 1h
callCloneBuildInstall $SEND_DEVICE_ID
fi
elif [ "$1" -eq -m ]; then
echo "Check for CloneBuildInstall"
if [ "$5" -eq pass ]; then
DEVICE_ID=$3
callCloneBuildInstall $SEND_DEVICE_ID
else
echo "call CloneBuildInstall"
# Zip log file and save it with deviceId
callCloneBuildInstall $SEND_DEVICE_ID
fi
fi
function callCloneBuildInstall {
./CloneBuildInstall.sh -d $SEND_DEVICE_ID
}
From help test:
[...]
STRING1 = STRING2
True if the strings are equal.
[...]
arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne,
-lt, -le, -gt, or -ge.
But in any case, each part of the condition is a separate argument to [.
if [ "$arg" -eq 0 ]; then
if [ "$arg" = 0 ]; then
Why not use something like
if [ "$#" -ne 0 ]; then # number of args should not be zero
echo "USAGE: "
fi
When/how to use “==” or “-eq” operator in test?
To put it simply use == when doing lexical comparisons a.k.a string comparisons but use -eq when having numerical comparisons.
Other forms of -eq (equal) are -ne (not equal), -gt (greater than), -ge (greater than or equal), -lt (lesser than), and -le (lesser than or equal).
Some may also suggest preferring (( )).
Examples:
[[ $string == "something else" ]]
[[ $string != "something else" ]] # (negated)
[[ $num -eq 1 ]]
[[ $num -ge 2 ]]
(( $num == 1 ))
(( $num >= 1 ))
And always use [[ ]] over [ ] when you're in Bash since the former skips unnecessary expansions not related to conditional expressions like word splitting and pathname expansion.
I have a Paas cron service that only run on minutely, hourly, daily, weekly. I want my script to run o every 15 minutes at 8am, 9am, 10am, 11am, 4pm and 5pm. how do I do that. Here is my not working bash script.
#!/bin/bash
MINUTES=`date +%M`
HOUR=`date +%H`
for j in "08" "09" "10" "11" "13" "16" "17";do
if [ "$HOUR" == "$j" ];then
for i in "00" "15" "30" "45";do
if [ "$MINUTES" == "$i" ];then
(
/usr/bin/notify-send "Script is running at "
)
fi
done
fi
done
Why don't just use the features of crontab?
Add this line to the crontab
*/15 8,9,10,11,16,17 * * * /path/bin/yourscript.sh
I'd be looking at something like (run by cron every minute):
#!/usr/bin/bash
# Exit if hour not valid.
hh=$(date +%H) ; hhn=${hh##0}
if [[ $hhn -lt 8 ]] ; then exit ; fi
if [[ $hhn -gt 17 ]] ; then exit ; fi
if [[ $hhn -eq 12 ]] ; then exit ; fi
if [[ $hhn -eq 14 ]] ; then exit ; fi
if [[ $hhn -eq 15 ]] ; then exit ; fi
# Exit if not multiple of 15 minutes.
mm=$(date +%M) ; mmn=${mm##0} ; ((mm15 = mmn % 15))
if [[ $mm15 -ne 0 ]] ; then exit ; fi
# Otherwise do something.
echo Doing something at $hh:$mm
This has the advantage of not doing a lot of loops to check whether or not you should run.
The ${hh##0} construct simply removes any leading zero from the hour so 08 and 09 can be used in arithmetic comparisons without being treated as invalid octal (ditto for the minute).
All of the if statements simply exit prematurely from the script if the hour and/or minute should prevent the run. The minute one is simpler since it's a modulo-15 calculation.
In bash shell, how can be value checked if within range by most effective way?
Example:
now=`date +%H%M`
if [ $now -ge 2245 ] && [ $now -le 2345 ] ; then
...
fi
...this one is working, but with using now variable.
Other option is:
if [ $((`date +%H%M`)) -ge 2245 ] && [ $((`date +%H%M`)) -le 2345 ] ; then
...
fi
...without variable, but with execution of date twice.
How to do it with one date execution and no variable at all?
First off, as a general rule, I'm pretty sure you need EITHER to use a variable OR run the command twice to do multiple comparisons on arbitrary numbers. There is no such notation as if [ 1000 -lt $(date '+%H%M') -lt 2000 ];.
Also, you don't need to put your backquoted commands inside $((...)). The result of the backquoted command is a string which /bin/[ will be interpreted by -gt or -le as a number.
if [ `date '+%H%M'` -gt 2245 -a `date '+%H%M'` -lt 2345 ]; then
That said, as an option for the times in your example, you can try using a smarter date command line.
In FreeBSD:
if [ `date -v-45M '+%H'` -eq 22 ]; then
Or in Linux:
if [ `date -d '45 minutes ago' '+%H'` -eq 22 ]; then
You can use Shell Arithmetic to make your code clear.
now=`date +%H%M`
if ((2245<now && now<2345)); then
....
fi
I would write:
if ( now=$(date +%H%M) ; ! [[ $now < 2245 ]] && ! [[ $now > 2345 ]] ) ; then
...
fi
which is mostly equivalent to your first example, but restricts the $now variable to a subshell (...), so at least it doesn't pollute your variable-space or risk overwriting an existing variable.
It also (thanks to shellter's comment) avoids the problem of $now being interpreted as an octal number when %H%M is (for example) 0900. (It avoids this problem by using string comparison instead of integer comparison. Another way to avoid this problem would be to prefix all values with a literal 1, adding 10,000 to each of them.)
#!/bin/bash
while :
do
MAX_TIME="1845"
MIN_TIME="1545"
if ( now=$(date +%H%M) ; ! [[ $now < $MIN_TIME ]] && ! [[ $now > $MAX_TIME ]] ) ;
then
echo "You are in time range and executing the commands ...!"
else
echo "Maximum Time is $MAX_TIME ...!"
# echo "Current Time is $now .....!"
echo "Minimum Time is $MIN_TIME ....!"
fi
sleep 4
done
#nohup sh /root/Date_Comp.sh > /dev/null 2>&1 &