I've got a bash shell that gets options as either month (mm) and year (yyyy) or time (mmyyyy).
I can parse options and assign them to variables. Now, I need some conditions to check for those variables. What I need is: if (month AND year) OR time then proceed else display usage. This is my code and it doesn't seem to be working.
if [[ -z $MONTH && -z $YEAR ]] || [[ -z $TIME ]]; then
usage
exit 1
else
if [[ -z $TIME ]]; then
echo $MONTH$YEAR
else
echo $TIME
fi
fi
Your logic is a bit backward. This:
if [[ -z $MONTH && -z $YEAR ]] || [[ -z $TIME ]]; then
usage
("if I'm missing both month and year, it's an error; or, if I have those, but am missing time, it's an error") should be this:
if [[ -z $MONTH || -z $YEAR ]] && [[ -z $TIME ]]; then
usage
("if I'm missing month or year, and I'm missing time, it's an error").
Related
I am writing a bash script that sometimes will use environment variables GIT_DIR and GIT_WORK_TREE. The bash script can only operate correctly if either both variables exist or neither exist. In case there's a technical difference, it makes no difference
This works, but there has to be a better way:
if [[ -z "${GIT_DIR}" ]]; then
_GIT_DIR_EXISTS=0
else
_GIT_DIR_EXISTS=1
fi
if [[ -z "${GIT_WORK_TREE}" ]]; then
_GIT_WORK_TREE_EXISTS=0
else
_GIT_WORK_TREE_EXISTS=1
fi
if [[ "${_GIT_DIR_EXISTS}" -ne "${_GIT_WORK_TREE_EXISTS}" ]]; then
echo "GIT_DIR is ${GIT_DIR}"
echo "GIT_WORK_TREE is ${GIT_WORK_TREE}"
echo "Both or none must exist"
exit 1
fi
I tried:
if [[ (-z "${GIT_DIR}") -ne (-z "${GIT_WORK_TREE}") ]]; then
But that gives this error:
bash: syntax error in conditional expression
bash: syntax error near '-ne'
I then resorted to trying semi-random things, with varying errors:
if [[ -z "${GIT_DIR}" -ne -z "${GIT_WORK_TREE}" ]]; then
if [[ [-z "${GIT_DIR}"] -ne [-z "${GIT_WORK_TREE}"] ]]; then
if [[ [[-z "${GIT_DIR}"]] -ne [[-z "${GIT_WORK_TREE}"]] ]]; then
if [[ -z "${GIT_DIR}" ]] ^ [[ -z "${GIT_WORK_TREE}" ]]; then
if { [[ -z "${GIT_DIR}" ]] } -ne { [[ -z "${GIT_WORK_TREE}" ]] }; then
if [[ (( -z "${GIT_DIR}" )) -ne (( -z "${GIT_WORK_TREE}" )) ]]; then
I tried:
if [[ $(test -z "${GIT_DIR}") -ne $(test -z "${GIT_WORK_TREE}") ]]; then
But realized that doesn't work because it's a sub-process, and they'd need to be exported. as Socowl comments, this compares the outputs of the test commands which output nothing, not their exit statuses.
I apologize if this is a duplicate. I've searched here and google for a while, and must not be using the right terminology.
How about this:
if [[ "${GIT_DIR:+set}" != "${GIT_WORK_TREE:+set}" ]]; then
echo "GIT_DIR is '${GIT_DIR}'"
echo "GIT_WORK_TREE is '${GIT_WORK_TREE}'"
echo "Both or none must exist"
exit 1
fi
Explanation: ${var:+value} is a variant of parameter expansion that gives "value" if var is set to a nonempty string, or the empty string if var is unset or empty. So if both vars are unset/empty, it becomes if [[ "" != "" ]]; then, and if they're both set it becomes if [[ "set" != "set" ]]; then etc.
BTW, if you want to test whether the variables are set at all (even if to the empty string), use ${var+value} (note the lack of colon). The bash manual lists the :+ version, but not the + version.
I need to get value from <2018-2099>, if user will type wrong value then script will tell him that value is incorrect and will ask him to type again.
I already have something like this but it doesn't work..
Any suggestions?
#!/bin/bash
read -r -p "Type year [value from 2019-2099]" year
if [[ "$year" =~ ^(20[1-9]|[1-9])+$ ]]; then
mkdir -p "/home/$year/"
else
echo "$year - value is not correct. Try again." >&2 && exit 1
fi
You can use function and until loop to achieve this, consider following code:
readYear() {
read -r -p "Type year [value from 2018-2099]" year
[[ "${year}" =~ ^[0-9]{4}$ ]] && [[ "${year}" -ge 2018 ]] && [[ "${year}" -le 2099 ]]
}
until readYear; do
echo "${year} - value is not correct. Try again." >&2
done
The function returns 0 if the value entered is valid, then the loop terminates.
You can try this:
until
read -r -p "Type year [2019-2099]: " year
[[ $year =~ ^2[0-9]+$ ]] && (( year >= 2018 && year <= 2099 ))
do
echo "Incorrect value" >&2
done
echo "OK: $year"
Here is my script:
age=119
if [[$age -gt 99 ]]; then
age_3digits=$age
elif [[$age -gt 9]]; then
age_3digits=0$age
else
age_3digits=00$age
fi
z_grid=${age_3digits}Ma.grd
echo $z_grip
output: 00119Ma.grd
how come?? I am new to bash, thanks so much
You need a space after [[ and before ]]. Change to:
if [[ $age -gt 99 ]]; then
age_3digits=$age
elif [[ $age -gt 9 ]]; then
age_3digits=0$age
else
age_3digits=00$age
fi
It's also better to use arithmetic expressions because it makes your code more readable, like this:
if (( age > 99 )); then
age_3digits=$age
elif (( age > 9 )); then
age_3digits=0$age
else
age_3digits=00$age
fi
I'm trying to print date range in AIX. I'm not able to use 'date' in AIX properly. I've tried some solutions suggested in Stack overflow. Nothing worked. Please find the error and code below.
I can't download 'GNU'.
#!/bin/ksh
startdate=20141030
enddate=20141120
loop_date=$startdate
let j=0
while [ "$loop_date" -ne "$enddate" ]; do
loop_date=`date -j -v+${j}d -f "%Y%m%d" "$startdate" +"%Y%m%d"`
echo $loop_date
let j=j+1
done
Error:
date: illegal option -- j
Usage: date [-u] [+Field Descriptors]
Try this;
#!/bin/ksh
startdate=$1
enddate=$2
loop_date=$startdate
currentdate=`date +%Y%m%d`
let j=0;
if [[ $startdate -lt $currentdate && $enddate -lt $currentdate ]];then
loop_date=$currentdate
while [[ "$loop_date" -gt "$startdate" ]]; do
loop_date=$(TZ=CST+$j date +%Y%m%d)
if [[ $loop_date -le $enddate ]];then
echo $loop_date
fi
let j=j+24
done
fi
if [[ $startdate -gt $currentdate && $enddate -gt $currentdate ]];then
while [[ "$loop_date" -lt "$enddate" ]]; do
loop_date=$(TZ=CST-$j date +%Y%m%d)
if [[ $startdate -le $loop_date ]];then
echo $loop_date
fi
let j=j+24
done
fi
user#host:/tmp:>ksh test.sh 20150630 20150705
20150705
20150704
20150703
20150702
20150701
20150630
user#host:/tmp:>ksh test.sh 20170630 20170705
20170630
20170701
20170702
20170703
20170704
20170705
I'm trying desperatly to find a bash or ksh routine that allows me to find for example the previous Monday,Tuesday,Wednesday,... preceding today's date. Additonal it has to work on plain vanilla Solaris X and I don't have the GNU date available.
eg: Today = Thursday 2013/01/17 ; Let's say I want to find the last Monday. It has to return:
2013/01/14
I've managed to find a script on the net that does the job perfectly for all days except in this specific case:
eg: Today = Thursday 2013/01/17 ; I want to find the last Thursday which should give as result: 2013/01/10 ; but instead I get todays date again.
The script used was this:
#!/bin/ksh
#Get the nbr of the current weekday (1-7)
DATEWEEK=`date +"%u"`
#Which previous weekday will we need (1-7)
WEEKDAY=$1
# Main part
#Get current date
DAY=`date +"%d"`
MONTH=`date +"%m"`
YEAR=`date +"%Y"`
#Loop trough the dates in the past
COUNTER=0
if [[ $DATEWEEK -eq $WEEKDAY ]] ; then
# I need to do something special for the cases when I want to find the date of the same day last week
DAYS_BACK=168
DAY=`TZ=CST+$DAYS_BACK date +%d`
echo "DAY (eq) = $DAY"
else
while [[ $DATEWEEK -ne $WEEKDAY ]] ; do
COUNTER=`expr $COUNTER + 1`
echo "Counter is: $COUNTER"
DAYS_BACK=`expr $COUNTER \* 24`
echo "DAYS BACK is: $DAYS_BACK"
DAY=`TZ=CST+$DAYS_BACK date +%d`
echo "DAY is: $DAY"
if [[ "$DAY" -eq 0 ]] ; then
MONTH=`expr "$MONTH" - 1`
if [[ "$MONTH" -eq 0 ]] ; then
MONTH=12
YEAR=`expr "$YEAR" - 1`
fi
fi
DATEWEEK=`expr $DATEWEEK - 1`
if [[ $DATEWEEK -eq 0 ]]; then
DATEWEEK=7
fi
done
fi
echo $DAY/$MONTH/$YEAR
(My previous suggestion didn't work as I thought. It was late last night ...)
The key thing is to ignore today, but still loop. Try it like this:
#!/bin/ksh
#Get the nbr of the current weekday (1-7)
DATEWEEK=`date +"%u"`
#Which previous weekday will we need (1-7)
WEEKDAY=$1
# Main part
#Get current date
DAY=`date +"%d"`
MONTH=`date +"%m"`
YEAR=`date +"%Y"`
#Loop trough the dates in the past
COUNTER=0
while [ $COUNTER -eq 0 ] || [[ $DATEWEEK -ne $WEEKDAY ]] ; do
COUNTER=`expr $COUNTER + 1`
echo "Counter is: $COUNTER"
DAYS_BACK=`expr $COUNTER \* 24`
echo "DAYS BACK is: $DAYS_BACK"
DAY=`TZ=CST+$DAYS_BACK date +%d`
echo "DAY is: $DAY"
if [[ "$DAY" -eq 0 ]] ; then
MONTH=`expr "$MONTH" - 1`
if [[ "$MONTH" -eq 0 ]] ; then
MONTH=12
YEAR=`expr "$YEAR" - 1`
fi
fi
DATEWEEK=`expr $DATEWEEK - 1`
if [[ $DATEWEEK -eq 0 ]]; then
DATEWEEK=7
fi
done
echo $DAY/$MONTH/$YEAR
Your DAY=`TZ=CST+$DAYS_BACK date +%d` trick doesn't work for me though. Linux date seems to cap it at one day.
Does this work?
today=$(date +"%u")
weekday=$1
curdate=$(date +"%s")
gobackdays=$(($today - $weekday))
if [ $gobackdays -le 0 ]; then
let gobackdays+=7
fi
SECSDAY=86400
backtime=$(($curdate - $gobackdays * $SECSDAY))
echo $(date -d "#$backtime")