How to create a date generator in shell? - shell

I want to pull some information from a website from past 4 years and each file is date based, like http://ransompull.com/pullme/2013-04-06/example.2013-04-06.txt
and it is the starting file and it ends today, so i want to pull all the txt files from last 4 years.
What I tried:
DATE=`date +%Y`
MONTH='01'
DAY='1'
for i in range(1,31);
for j in range(01,12):
do wget http://ransompull.com/pullme/$DATE$i/example.$DATE$i.txt;
done
done
But this seems to wrong as iterating over month and date is not feasible as it is not giving desired output.Any suggestions on how to pull all data from
http://ransompull.com/pullme/2013-04-06/example.2013-04-06.txt
to
http://ransompull.com/pullme/2017-08-10/example.2017-08-10.txt

Instead of counting years, months and days,
you could just count days relative to the start date.
If you have the GNU implementation of the date command,
you can use it to compute the relative date, for example:
date +%F -d '2013-04-06 + 1000 days'
This outputs 2016-01-01.
You can create a loop, generating dates by incrementing the number of days from start, until you reach the end:
start=2013-04-06
end=2017-08-10
date=$start
days=0
while [ "$date" != "$end" ]; do
date=$(date +%F -d "$start + $days days")
wget http://ransompull.com/pullme/$date/example.$date.txt
((days++))
done

try this:
$startdate=get-date 2017-08-11
$enddate=$startdate.AddYears(-4)
0..($startdate - $enddate).Days | %{wget ("http://ransompull.com/pullme/{0:yyyy-MM-dd}/example.{0:yyyy-MM-dd}.txt" -f $startdate.AddDays(-$_))}

Related

Yesterday's date variable in BASH on AIX Server

I want to store yesterday's date in BASH variable to search for yesterday's files with that variable in the file-name wildcard search. I am using the following format for New York City, NY, USA (EST) time zone, and wanted to know whether it is guaranteed to fetch yesterday's date from the system date; else I can make further changes to the variable.
yesterday=$(TZ=GMT+28 date +%Y%m%d)
...
for file in $HOME_DIR/*$yesterday*.txt;
...
The text filename in HOME_DIR would be as follows:
"ABC_20171011064612.txt"
update 1: Attempt for removing daylight savings related issues:
yesterday=$(echo -e "$(TZ=GMT+28 date +%Y%m%d)\n$(TZ=GMT+18 date +%Y%m%d)"|grep -v $(date +%Y%m%d)|sort|tail -1)
1) Convert two dates to string, 24 hours and 14 (picked arbitrarily to be less than 24 hours) hours before today's date
2) Filter for dates that are not today's date
3) Sort strings from 2) in ascending order
4) Assign yesterday variable to last tail -1 entry of the list
It may not be always right due to DST, although it will not be a big issue.
You could rather say:
yesterday=$(date -d yesterday +%Y%m%d)
You attempted
yesterday=$(echo -e "$(TZ=GMT+28 date +%Y%m%d)\n$(TZ=GMT+18 date +%Y%m%d)|
grep -v $(date +%Y%m%d)|sort|tail -1)
I think it worked.

subtracting two lists of timestamps from each other in bash

I have a script that checks my logs for the timestamps of when the application has gone down and back up (availability of the app).
I want to find the difference between a list of timestamps then add up all of those difference so I know a total amount of time the app has been down. So the downtime.txt file has a list like this:
04:55:51
05:41:51
and the uptime.txt has a list like the same format:
04:56:59
05:42:21
If I didn't need to convert the timestamps into numbers for arithmetic I think I could
paste downtime.txt uptime.txt | awk '{print $1 - $2}'>timedown.txt
or something like that. How can I read the timestamps, convert it to a number, subtract the matching lines from the two files, then add up all the sums from those lines?
You can use the date command to convert timestamps. It's unfortunate your timestamps don't have dates on them, not sure what happens when you roll over past midnight, but assuming you don't have that problem, you can choose the fixed date "01-Jan-1970 UTC" for calculation purposes.
Here is your code:
paste downtime.txt uptime.txt | while read d u; do echo $(( $(date -d "01-Jan-1970 UTC $u" +%s) - $(date -d "01-Jan-1970 UTC $d" +%s) )); done
Explanation: The date command converts the timestamps into seconds. The -d option means, act on the following date instead of "now". So we give it a date using your input files, assuming that the times specified are from midnight. Since date works on the basis of seconds since 01 Jan 1970 UTC 00:00:00, we add that date to simplify the result. The +%s parameter means, tell me how many seconds it is since 01-Jan-1970. This is where the conversion comes in. Since we specified -d, it uses the timestamp you specified instead of "now". So the value of $(date -d "01-Jan-1970 UTC $u" +%s) is the number of seconds since midnight for the uptime. Then we subtract the downtime seconds from the uptime seconds using $(( ... )) to get the number of seconds between the two timestamps. (If your bash doesn't have that function, you can use $(expr $(date -d "01-Jan-1970 UTC $u" +%s) - $(date -d "01-Jan-1970 UTC $d" +%s) ) instead).
UPDATE: I should finish the job. To accumulate and count the total time, you can add | awk '{total=total+$1} END {print $total}'. To convert this back into hours and minutes, use date again; use the -u option to prevent conversion to local time, the -d option with # to specify number of seconds (again we are using 01-Jan-1970 as a base, that's what # means), and +%T to convert into hours and minutes, though if it's more than 24 hours you'll lose the extra days.
date -u -d #$(paste downtime.txt uptime.txt | while read d u; do echo $(( $(date -d "01-Jan-1970 UTC $u" +%s) - $(date -d "01-Jan-1970 UTC $d" +%s) )); done | awk '{total=total+$1} END {print total}') +%T

Remove all lines in file older than 24 hours

Ive seen a lot of questions regarding removing files that are older than x number of hours. I have not seen any pertaining to removing lines in a file older than x number of hours.
Here is an example of the log I am dealing with. For the sake of the example, assume current time is 2016-12-06 06:08:48,594
2016-12-05 00:44:48,194 INFO this line should be deleted
2016-12-05 01:02:10,220 INFO this line should be deleted
2016-12-05 05:59:10,540 INFO this line should be deleted
2016-12-05 06:08:10,220 INFO this line should be deleted
2016-12-05 16:05:30,521 INFO do not delete this line
2016-12-05 22:23:08,623 INFO do not delete this line
2016-12-06 01:06:28,323 INFO do not delete this line
2016-12-06 05:49:55,619 INFO do not delete this line
2016-12-06 06:06:55,419 INFO do not delete this line
I realize that it might be easier to do this in python or Perl but this needs to be done in bash. That being said, please post any and all relevant answers.
So far Ive tried using sed, awk, etc to convert the timestamps to seconds.
#! /bin/bash
TODAY=$(date +%Y-%m-%d)
# one day ago
YESTERDAY=$(date -d #$(( $(date +"%s") - 86400)) +%Y-%m-%d)
REPORT_LOG=report_log-$TODAY.log
# current date in seconds
NOW=$(date +%s)
# oldest date in the log trimmed by timestamp
OLDEST_DATE=$(head -1 $REPORT_LOG | awk '{print $1" "$2}')
# oldest date converted to seconds
CONVERT_OLDEST_DATE=$(date -d "$OLDEST_DATE" +%s)
TIME_DIFF=$(($NOW-$CONVERT_OLDEST_DATE))
# if difference is less than 24 hours, then...
if [ $TIME_DIFF -ge 86400 ]; then
LATEST_LOG_TIME=$(tail -1 $REPORT_LOG | awk '{print $2}'| cut -c 1-8)
RESULTS=$(awk "/${YESTERDAY} ${LATEST_LOG_TIME}/{i++}i" $REPORT_LOG)
if [ -z $RESULTS]; then
awk "/${YESTERDAY} ${LATEST_LOG_TIME}/{i++}i" $REPORT_LOG > $REPORT_LOG.tmp && mv $REPORT_LOG.tmp $REPORT_LOG
else
echo "Out of ideas at this point"
fi
else
echo "All times newer than date"
fi
The problem with my above snippet is that it relies on a date to repeat itself for the awk to work, which is not always the case. There are hour long gaps in the log files so it is possible for the last line's date (ex. 2016-12-06 06:06:55) to be the only time that date appears. If the timestamp has not previously appeared, my script will delete all results before the matched timestamp.
Any and all help is appreciated.
awk to the rescue!
$ awk -v d="2016-12-05 06:08:48,594" '($1 " " $2) > d' file
will print the newer entries. Obviously, you want to create the date dynamically.
Ignoring the milliseconds part to simplify, you can use
$ awk -v d="$(date --date="yesterday" "+%Y-%m-%d %H:%m:%S,999")" ...
Note that lexical comparison works only for your hierarchial formatted date (why don't everybody use this?), for any other format you are better off converting to seconds from epoch and do numerical comparison on integers
Do the dates in times since the Unix epoch, using the format string +%s. For instance:
yesterday=$(date --date="yesterday" +%s)
Then interpret the dates you've extracted with awk or similar like:
dateInUnixEpoch=$(date --date="$whateverDate" +%s)
Then just compare the dates:
if [ "$yesterday" -ge "$dateInUnixEpoch" ];
then do whatever to delete the lines
fi

Taking date and time of last 5 days

I know that I can take date and time of yesterday by writing
dt=`date +"%d-%m-%Y" -d "-1 day"`
Similarly I want to find -2 day, -3 day and so on. When I put this command in loop, and write it as
dt=`date +"%d-%m-%Y" -d "-$i day"`
it didn't worked. Am I wrong somewhere or there is some another way to do such stuff.

Unix Shell scripting - calculating last week date based on given date

Need a help in unix shell script in calculating date.
I will be getting date value (eg: 20150908) as parameter, now inside the script i need to calculate 7 days ago date (20150908 -7).
something like below:
date=20150908
lastweek_date=20150908 - 7 ---> this should output as 20150901
Could someone help me on this.
Thanks
With GNU date, we can subtract one week:
$ date -d "20150908 - 1 week" '+%Y%m%d'
20150901
Alternatively, we could subtract 7 days:
$ date -d "20150908 - 7 days" '+%Y%m%d'
20150901
And, to show that this works over month boundaries:
$ date -d "20150901 - 1 week" '+%Y%m%d'
20150825
This solution is not OSX/BSD compatible.
A week is 604800 seconds long so to get the number of seconds since the epoch in a portable and POSIX compliant fashion and use it to compute the date 1 week ago do as follows:
PRESENT=$( date +%s )
WEEKAGO=$(( PRESENT - 604800 ))
printf "%s\n" "$WEEKAGO"

Resources