Comma separated values of dates - shell

I have code that prints dates incorrectly
condition=`date -d "20150209" +%a`
start_date=`date -d -7day"20150209" +%Y%m%d`
end_date=`date -d -1day"20150209" +%Y%m%d`
if [ "$condition" = "Mon" ]
then
while [ "$start_date" != "$end_date" ]
do
Date+=$start_date,
start_date=$(date -d +1day"$start_date" +%Y%m%d)
done
echo "$Date"
fi
I am expecting output as
20150203,20150204,20150205,20150206,20150207,20150208
I am unable to figure out what is wrong.

I was missing the last element in the date range.
here is the solution.
condition=`date -d "20150209" +%a`
start_date=`date -d -7day"20150209" +%Y%m%d`
end_date=`date -d -1day"20150209" +%Y%m%d`
while [ "$start_date" != "$end_date" ]
do
Date+=$start_date,
start_date=$(date -d +1day"$start_date" +%Y%m%d)
done
echo "$Date$end_date"
if someone has a better solution please let me know.

Related

Bash: start date less than equal to end date

#!/bin/bash
# slightly malformed input data
input_start=2014-11-1
input_end=2016-01-1
# After this, startdate and enddate will be valid ISO 8601 dates,
# or the script will have aborted when it encountered unparseable data
# such as input_end=abcd
startdate=$(date -I -d "$input_start") || exit -1
enddate=$(date -I -d "$input_end") || exit -1
m="$startdate"
while [ "$m" != "$enddate" ]; do
echo $m
m=$(date -I -d "$m + 1 month")
done
"Script is running fine but when I want to change the While loop condition i.e '<=' 'less then or equal to' its giving error even I tried using "-le".What I want to do here is startdate <= enddate in while loop. Can anyone suggest what needs to done to overcome this issue.
Same Code
-le is for numeric data. 2014-11-01 is not a number. Use < or >. (You need to escape them as \< or \>. Or use [[ instead of [.)
effectively, change
while [ "$m" != "$enddate" ]; do
to
until [ "$m" \> "$enddate" ]; do
or
until [ "$m" '>' "$enddate" ]; do
or
until [[ "$m" > "$enddate" ]]; do
Alternately, use seconds since epoch instead of ISO8601 format.
while [ "$(date -d "$m" +%s)" -le "$(date -d "$enddate" +%s)" ]; do
With dateutils' datetest this is simple:
$ datetest 2014-11-1 --le 2016-01-1 ; echo $?
0
$ datetest 2014-11-1 --gt 2016-01-1 ; echo $?
1
Then again, what you want is simply done by dateseq, which also happens to be a tool of the dateutils suite.
$ dateseq 2014-11-1 +1mo 2016-01-1
2014-11-01
2014-12-01
2015-01-01
2015-02-01
2015-03-01
2015-04-01
2015-05-01
2015-06-01
2015-07-01
2015-08-01
2015-09-01
2015-10-01
2015-11-01
2015-12-01
2016-01-01
Disclaimer: I am the author of the package.

Error Converting String to Date in Shell

Hi I get the below error when I try to execute the below code:
date_input= '2015-01-25'
date_parameter=$(date -d `echo $date_input` +%s)
min_date=$(date -d 2015-11-01 +%s)
max_date=$(date -d $(date +"%Y-%m-%d") +%s)
if [ "$date_parameter" -gt "$max_date" ] || [ "$date_parameter" -lt "$min_date" ]; then
Error -> [: : integer expression expected
You can fix your script by using:
date_input='2015-01-25'
date_parameter=$(date -d "$date_input" '+%s')
min_date=$(date -d 2015-11-01 '+%s')
max_date=$(date '+%s')
[[ $date_parameter -gt $max_date || $date_parameter -lt $min_date ]] &&
echo "ok" || echo "nope"
Remove whitespace after = in first line.

Bash Script for deleting old backup files

every night my server creates backups for every mysql database. All of these files are saved in a folder like /backup/mysql/2014-11-28. Over the last few months a lot of folders and files have been stored in that directory and I would like to reduce this.
Therefore I would need a bash script which deletes every folder in the given directory, except every folder created this month (not in the last 30 days, but the actual month) and except one backup from every week (for example the backup from sunday). Since I have no clue how to do the sunday party I decided it would be simpler to keep the backups from the 07th, the 14th, the 21st and the the 28th.
#!/bin/bash
in_array() {
local haystack=${1}[#]
local needle=${2}
for i in ${!haystack}; do
if [[ ${i} == ${needle} ]]; then
return 0
fi
done
return 1
}
YEAR=`date +%Y`
LASTYEAR=`date +%Y -d "1 year ago"`
MONTH=`date +%m`
DAYS="07 14 21 28"
for i in $( ls ); do
BACKUP_YEAR=$(echo "${i}" | cut -d'-' -f1)
BACKUP_MONTH=$(echo "${i}" | cut -d'-' -f2)
BACKUP_DAY=$(echo "${i}" | cut -d'-' -f3)
DELETE=false
if [[ "$BACKUP_YEAR" == "$YEAR" ]]; then
if [[ "$BACKUP_MONTH" != "$MONTH" ]]; then
if [ $(in_array $DAYS "$BACKUP_DAY") ]; then
DELETE=true
fi
fi
fi
if [[ "$BACKUP_YEAR" == "$LASTYEAR" ]]; then
if [[ "$BACKUP_DAY" != ${DAYS[0]} ]]; then
DELETE=true
fi
fi
if [ "$DELETE" = true ] ; then
#OUTPUT=`rm -v -R $i`
echo $i
fi
done
The second part (backups from the year before) works perfectly fine, but the first part (for backups from this year) doesn't work and I don't know why. I found the function on this site, but I guess somehow my call is wrong.
EDIT: The code I am now using:
#!/bin/bash
read YEAR MONTH <<<$(date "+%Y %m")
LASTYEAR=$(( YEAR-1 ))
DAYS=" 07 14 21 28 "
for fn in $( ls )
do
if ([ "${fn:0:4}" = "$YEAR" ] &&
[ "${fn:5:2}" != "$MONTH" ] &&
[ "${DAYS/ ${fn:8:2} /}" = "$DAYS" ]) || ([ "${fn:0:4}" = "$LASTYEAR" ] &&
[ "${fn:8:2}" != ${DAYS:1:2} ])
then
#OUTPUT=`rm -v -R $fn`
echo "$fn"
fi
done
#!/bin/bash
read YEAR MONTH <<<$(date "+%Y %m")
LASTYEAR=$(( YEAR-1 ))
DAYS=" 07 14 21 28 "
for fn in $( ls )
do
DELETE=false
if [ "${fn:0:7}" = "$YEAR-$MONTH" ] &&
[ "${DAYS/ ${fn:8:2} /}" != "$DAYS" ]
then
DELETE=true
elif [ "${fn:0:4}" = "$LASTYEAR" ] &&
[ "${fn:8:2}" != ${DAYS:1:2} ]
then
DELETE=true
fi
if [ "$DELETE" = true ]
then
#OUTPUT=`rm -v -R $fn`
echo "$fn"
fi
done
Assuming that a file name matches the following date format YYYY-MM-DD, for instance, 2014-03-27, the expression ${fn:0:7} would be 2014-03; ${fn:8:2} would be 27; ${fn:0:4} would be 2014.
Read the bash manual pages about the parameter expansion.
The expression ${DAYS/ ${fn:8:2} /} checks the day from the filename (wrapped by white spaces) is found in the DAYS list. It would be equivalent to echo "${DAYS}" | grep -q "${BACKUP_DAY}".
note: it is possible to reduce the commands inside the for loop (join if and elif by means of a || and remove the DELETE variable checking and the DELETE variable itself) but I decided to keep the look of the original script.

Logical AND in shell script while loop

I am trying to compare dates in the while loop of a shell script. The shell script will be controlled by 2 conditions, like the following:
while [ $currentDate -le $currentDateMonthEnd -a $currentDate -le $toDate ]; do
...
done
The above is my current code, which complains of "integer expression expected". I have also tried using && and AND, which also do not work and complains of mismatching braces.
Could someone please provide the syntax to make the above comparison?
dc ()
{
[ $(date +%s -d "$1") $2 $(date +%s -d "$3") ]
}
while dc "$currentDate" -le "$currentDateMonthEnd" && dc "$currentDate" -le "$toDate"
do
# ...
done
following code works for me,
#! /bin/bash
toDate=`echo 2014/03/30 | tr -d "/"`
currentDate=`date +"%Y/%m/%d" | tr -d "/"`
currentDateMonthEnd=`date +%Y/%m/%d -d "-$(date +%d) days +1 month" | tr -d "/"`
while [[ $currentDate -le $currentDateMonthEnd ]] && [[ $currentDate -le $toDate ]]
do
...
done
#! /bin/sh
while [ $currentDate -le $currentDateMonthEnd ] && [ $currentDate -le $toDate ]
do
...
done

bash shell script for yesterdays date (last working day)

I am writing a bash script that needs to print the date of the last working day. So for example if the script is run on a Monday, it will print the date for last Friday.
I found that this prints yesterdays date:
date -d '1 day ago' +'%Y/%m/%d'
I also know that I can get the day of the week by using this statement
date +%w
I want to combine these two statements in order to have a little helper script that prints the required date. The logic goes something like this (note: its Pseudo code - I've never written a bash script)
DAY_OF_WEEK = `date +%w`
if (%DAY_OF_WEEK == 1)
LOOK_BACK = 3
elif
LOOK_BACK = 1
fi
echo `date -d '%LOOK_BACK day ago' +'%Y/%m/%d'`
Can someone help by correcting the pseudo code above?
(I am running on Ubuntu 10.0.4)
You were so close:
day_or_week=`date +%w`
if [ $day_or_week == 1 ] ; then
look_back=3
else
look_back=1
fi
date -d "$look_back day ago" +'%Y/%m/%d'
Sunday also needs to be checked.
DAY_OF_WEEK=`date +%w`
if [ $DAY_OF_WEEK = 0 ] ; then
LOOK_BACK=2
elif [ $DAY_OF_WEEK = 1 ] ; then
LOOK_BACK=3
else
LOOK_BACK=1
fi
date -d "$LOOK_BACK day ago" +'%Y/%m/%d'
I'm using a Mac, so my date command doesn't have the same -d flag yours seems to, but the following should work if it behaves as you've indicated:
if [[ $(date +%w) == 1 ]]
then
LOOK_BACK=3
else
LOOK_BACK=1
fi
date -d "${LOOK_BACK} day ago" +%Y/%m/%d
For OSX (tested on 10.9.2 and 10.13.4), so probably any environment where you are using BSD date.
if [ $(date +%w) == 1 ] ; then
date -v-3d +'%Y/%m/%d'
else
date -v-1d +'%Y/%m/%d'
fi
You can check to see if you are using BSD date by
$ man date | grep "BSD General"
Putting the other answers together, I came up with this:
last_workday() {
from_date="${#:-today}"
day_of_week=$(date +%w --date="${from_date}")
if [ ${day_of_week} = "0" ] ; then
look_back=2
elif [ ${day_of_week} = "1" ] ; then
look_back=3
else
look_back=1
fi
date -d "${from_date} - ${look_back} day" +'%Y/%m/%d'
}
next_workday() {
from_date="${#:-today}"
day_of_week=$(date +%w --date="${from_date}")
if [ ${day_of_week} = "5" ] ; then
look_forward=3
elif [ ${day_of_week} = "6" ] ; then
look_forward=2
else
look_back=1
fi
date -d "${from_date} + ${look_forward} day" +'%Y/%m/%d'
}
for i in $(seq 16); do
now=$(date +'%Y/%m/%d' --date="today + ${i} day")
prev=$(last_workday "${now}")
next=$(next_workday "${now}")
echo "${now}: ${prev} ${next}"
done
A more concise form using a bash inline "ternary" expression:
[[ $(date +%w) == 1 ]] && days=3 || days=1
date -d "$days day ago" +"%Y-%m-%d"

Resources