I need to write a shell script that will create a list of 5 minutes interval times.
00-00
00-05
00-10
00-15
...
...
23-50
23-55
Here are the commands I have started with.
# date
Fri Sep 21 18:14:35 IST 2012
# date '+%H-%M'
18-14
# date '+%H-%M' --date='5 minute ago'
18-18
How do I write a script to generate the list?
If it is too complicated, I will do it manually since it is one time task.
Update:
The following script is working. But it will generate single digits like 7-5 should actually be 07-05
#!/bin/sh
for hour in `seq 0 24`
do
for minute in `seq 0 5 59`
do
echo $hour-$minute
done
done
A simple bash solution (version 4 or later):
printf "%s\n" {00..23}-{00..55..5}
If you need to start at a given date, you can use:
ITERATIONS=100 # adjust here
D=$(date +%s)
for ((i=0; i<$ITERATIONS; i++))
do
date '+%H-%M' -d #$((D+5*60*i))
done
The following shell scripting is returning the required data
#!/bin/sh
for hour in `seq -w 0 24`
do
for minute in `seq -w 0 5 59`
do
echo $hour-$minute
done
done
Related
At the moment, I have a while-loop that takes a starting date, runs a python script with the day as the input, then takes the day + 1 until a certain due date is reached.
day_start=2016-01-01
while [ "$day_start"!=2018-01-01 ] ;
do
day_end=$(date +"%Y-%m-%d" -d "$day_start + 1 day")
python script.py --start="$day_start" --end="$day_end";
day_start=$(date +"%Y-%m-%d" -d "$day_start + 1 day")
done
I would like to do the same thing, but now to pick a random day between 2016-01-01 and 2018-01-01 and repeat until all days have been used once. I think it should be a for-loop instead of this while loop, but I have trouble to specify the for-loop over this date-range in bash. Does anyone have an idea how to formulate this?
It can take quite a long time if you randomly choose the dates because of the Birthday Problem. (You'll hit most of the dates over and over again but the last date can take quite some time).
The best idea I can give you is this:
Create all dates as before in a while loop (only the day_start-line)
Output all dates into a temporary file
Use sort -R on this file ("shuffles" the contents and prints the result)
Loop over the output from sort -R and you'll have dates randomly picked until all were reached.
Here's an example script which incorporates my suggestions:
#!/bin/bash
day_start=2016-01-01
TMPFILE="$(mktemp)"
while [ "$day_start" != "2018-01-01" ] ;
do
day_start=$(date +"%Y-%m-%d" -d "$day_start + 1 day")
echo "${day_start}"
done > "${TMPFILE}"
sort -R "${TMPFILE}" | while read -r day_start
do
day_end=$(date +"%Y-%m-%d" -d "$day_start + 1 day")
python script.py --start="$day_start" --end="$day_end";
done
rm "${TMPFILE}"
By the way, without the spaces in the while [ "$day_start" != "2018-01-01" ];, bash won't stop your script.
Fortunately, from 16 to 18 there was no leap year (or was it, and it just works because of that)?
Magic number: 2*365 = 730
The i % 100, just to have less output.
for i in {0..730}; do nd=$(date -d "2016/01/01"+${i}days +%D); if (( i % 100 == 0 || i == 730 )); then echo $nd ; fi; done
01/01/16
04/10/16
07/19/16
10/27/16
02/04/17
05/15/17
08/23/17
12/01/17
12/31/17
With the format instruction (here +%D), you might transform the output to your needs, date --help helps.
In a better readable format, and with +%F:
for i in {0..730}
do
nd=$(date -d "2016/01/01"+${i}days +%F)
echo $nd
done
2016-01-01
2016-04-10
2016-07-19
...
For a random distribution, use shuf (here, for bevity, with 7 days):
for i in {0..6}; do nd=$(date -d "2016/01/01"+${i}days +%D); echo $nd ;done | shuf
01/04/16
01/07/16
01/05/16
01/01/16
01/03/16
01/06/16
01/02/16
I need to sort data on a weekly base and all i have are dates in a logfile.
Therefore to sort out data per week i would like to create a list with the dates of all mondays for a given year. I have tried to work something out and the only idea i currently have is to use ncal with year and month as argument looping over all months and extracting all mondays. Isn't there a more efficient way?
To get all mondays, by getting all dates and filtering by Mondays:
for i in `seq 0 365`
do date -d "+$i day"
done | grep Mon
Of course, you could also take a monday and keep incrementing by 7 days.
hope that's what you mean. Below can be changed to vary the output formats of the dates.
date command can be used for that, dunno if ncal is any more/less efficient.
I know you went for "binning" now, but here is a more readable v.
$ cat /tmp/1.sh
#!/bin/bash
test -z "$year" && {
echo "I expect you to set \$year environment variable"
echo "In return I will display you the Mondays of this year"
exit 1
}
# change me if you would like the date format to be different
# man date would tell you all the combinations you can use here
DATE_FORMAT="+%Y-%m-%d"
# change me if you change the date format above. I need to be
# able to extract the year from the date I'm shoing you
GET_YEAR="s/-.*//"
# this value is a week, in milliseconds. Changing it would change
# what I'm doing.
WEEK_INC=604800
# Use another 3-digit week day name here, to see dates for other week days
DAY_OF_WEEK=Mon
# stage 1, let's find us the first day of the week in this year
d=1
# is it DAY_OF_WEEK yet?
while test "$(date -d ${year}-1-${d} +%a)" != "$DAY_OF_WEEK"; do
# no, so let's look at the next day
d=$((d+1));
done;
# let's ask for the milliseconds for that DAY_OF_WEEK that I found above
umon=$(date -d ${year}-1-${d} +%s)
# let's loop until we break from inside
while true; do
# ndate is the date that we testing right now
ndate=$(date -d #$umon "$DATE_FORMAT");
# let's extract year
ny=$(echo $ndate|sed "$GET_YEAR");
# did we go over this year? If yes, then break out
test $ny -ne $year && { break; }
# move on to next week
umon=$((umon+WEEK_INC))
# display the date so far
echo "$ndate"
done
No need to iterate over all 365 or 366 days in the year. The following executes date at most 71 times.
#!/bin/bash
y=2011
for d in {0..6}
do
if (( $(date -d "$y-1-1 + $d day" '+%u') == 1)) # +%w: Mon == 1 also
then
break
fi
done
for ((w = d; w <= $(date -d "$y-12-31" '+%j') - 1; w += 7))
do
date -d "$y-1-1 + $w day" '+%Y-%m-%d'
done
Output:
2011-01-03
2011-01-10
2011-01-17
2011-01-24
2011-01-31
2011-02-07
2011-02-14
2011-02-21
2011-02-28
2011-03-07
. . .
2011-11-28
2011-12-05
2011-12-12
2011-12-19
2011-12-26
Another option that I've come up based on the above answers. The start and end date can now be specified.
#!/bin/bash
datestart=20110101
dateend=20111231
for tmpd in {0..6}
do
date -d "$datestart $tmpd day" | grep -q Mon
if [ $? = 0 ];
then
break
fi
done
for ((tmpw = $tmpd; $(date -d "$datestart $tmpw day" +%s) <= $(date -d "$dateend" +%s); tmpw += 7))
do
echo `date -d "$datestart $tmpw day" +%d-%b-%Y`
done
You can get the current week number using date. Maybe you can sort on that:
$ date +%W -d '2011-02-18'
07
Tl;dr: Is there a nice way of creating a sequence of dates with 12 hour increment in the format yyyymmddHHMM in the bash?
Consider I have a python-script which accepts a certain time (yyyymmddHHMM) as input -t, i could run it like this for instance
python myscript.py -t 201411140000
which the then starts myscript.pyfor the date 2014-11-14 00:00. Now I want to run the script for many dates, beginning from 2014-01-01 00:00 to 2014-11-14 00:00 with an increment of 12 hours, i.e. i want to produce all the following lines:
python myscript.py -t 201401010000
python myscript.py -t 201401011200
python myscript.py -t 201401020000
.
.
.
python myscript.py -t 201411131200
python myscript.py -t 201411140000
The closest to what I came is (echo to verify results without running them):
for mm in {01..10}; do for dd in {01..31}; do for HH in 00 12; do echo python myscript.py -t 2014$mm$dd$HH\00; done; done; done
It produces all required dates from Jan to Oct, but also some absurd dates, such as 201402310000, which the program then has to handle (i.e. throw/log errors). That is not a huge issue, but it feels dirty.
In the end, another loop is required to handle the missing dates Nov-01 to Nov-14, which, again, seems dirty to me.
How can I create those dates more nicely - or is the way above the appropriate way of doing so?
You can convert the start date to a UNIX timestamp, and iterate over the range in 43200-second (12-hour) increments.
for ((ts=$(date +%s --date "2014-11-01 0000");
ts <= $(date +%s --date "2014-11-14 0000");
ts+=12*3600)); do
python myscript.py -t $(date +%Y%m%d%H%M --date #$ts)
done
Using the -d option:
$>for i in $(seq 0 12 72); do
date -d "+$i hours" +%Y%m%d%H%M;
done
201411141544
201411150344
201411151544
201411160344
201411161544
201411170344
201411171544
And if you want a starting date (thanks to chepner):
$> for i in $(seq 0 12 72); do
date -d "2014-11-01 0000 +$i hours" +%Y%m%d%H%M;
done
201411010000
201411011200
201411020000
201411021200
201411030000
201411031200
201411040000
Numeric addition to processed dates is bad practice - there are many edge cases and gotchas. It's just a bad plan.
Fortunately, most computers don't do that. Unix systems use 'epoch' time, which is a count of seconds since 1970.
So you can numerically add 12 hours in seconds (12 * 60 * 60).
In perl, I'd do it like this:
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
my $t = localtime();
my $num = 300;
for ( 1 .. $num ) {
$t += 12 * 60 * 60;
print $t -> strftime ( "%y%m%d%H%M" ), "\n";
}
That'll do 12 hour cycles starting from right now. Shifting to midnight is left as an exercise for the reader :).
say that i am trying to do a echo TZ=GMT-24 date +%Y%m%d >> echoed.
This is in solaris.
Now, i would like to do a loop that reads a specific number of days and echoes with GMT-24/GMT-48 etc... until the number of days ends... this is a 5 times loop.... basicly from monday to friday. i will set this script on crontab that will run in one day and generates that echo output to a file so other script that i already have created can check those dates and work with them.
thanks in advance
This is ksh on Solaris 8:
$ date +%Y%m%d
20130919
$ for i in 1 2 3 4 5; do TZ=GMT-$(($i * 24)) date +%Y%m%d; done
20130920
20130921
20130922
20130923
20130924
$ for i in 1 2 3 4 5; do TZ=GMT+$(($i * 24)) date +%Y%m%d; done
20130918
20130917
20130916
20130915
20130914
To redirect to a file, add > filename after the done keyword
I need to create a bash shell script starting with a day and then loop through each subsequent day formatting that output as %Y_%m_d
I figure I can submit a start day and then another param for the number of days.
My issue/question is how to set a DATE (that is not now) and then add a day.
so my input would be 2010_04_01 6
my output would be
2010_04_01
2010_04_02
2010_04_03
2010_04_04
2010_04_05
2010_04_06
[radical#home ~]$ cat a.sh
#!/bin/bash
START=`echo $1 | tr -d _`;
for (( c=0; c<$2; c++ ))
do
echo -n "`date --date="$START +$c day" +%Y_%m_%d` ";
done
Now if you call this script with your params it will return what you wanted:
[radical#home ~]$ ./a.sh 2010_04_01 6
2010_04_01 2010_04_02 2010_04_03 2010_04_04 2010_04_05 2010_04_06
Very basic bash script should be able to do this:
#!/bin/bash
start_date=20100501
num_days=5
for i in `seq 1 $num_days`
do
date=`date +%Y/%m/%d -d "${start_date}-${i} days"`
echo $date # Use this however you want!
done
Output:
2010/04/30
2010/04/29
2010/04/28
2010/04/27
2010/04/26
Note: NONE of the solutions here will work with OS X. You would need, for example, something like this:
date -v-1d +%Y%m%d
That would print out yesterday for you. Or with underscores of course:
date -v-1d +%Y_%m_%d
So taking that into account, you should be able to adjust some of the loops in these examples with this command instead. -v option will easily allow you to add or subtract days, minutes, seconds, years, months, etc. -v+24d would add 24 days. and so on.
#!/bin/bash
inputdate="${1//_/-}" # change underscores into dashes
for ((i=0; i<$2; i++))
do
date -d "$inputdate + $i day" "+%Y_%m_%d"
done
Very basic bash script should be able to do this.
Script:
#!/bin/bash
start_date=20100501
num_days=5
for i in seq 1 $num_days
do
date=date +%Y/%m/%d -d "${start_date}-${i} days"
echo $date # Use this however you want!
done
Output:
2010/04/30
2010/04/29
2010/04/28
2010/04/27
2010/04/26
You can also use cal, for example
YYYY=2014; MM=02; for d in $(cal $MM $YYYY | grep "^ *[0-9]"); do DD=$(printf "%02d" $d); echo $YYYY$MM$DD; done
(originally posted here on my commandlinefu account)
You can pass a date via command line option -d to GNU date handling multiple input formats:
http://www.gnu.org/software/coreutils/manual/coreutils.html#Date-input-formats
Pass starting date as command line argument or use current date:
underscore_date=${1:-$(date +%y_%m_%d)}
date=${underscore_date//_/-}
for days in $(seq 0 6);do
date -d "$date + $days days" +%Y_%m_%d;
done
you can use gawk
#!/bin/bash
DATE=$1
num=$2
awk -vd="$DATE" -vn="$num" 'BEGIN{
m=split(d,D,"_")
t=mktime(D[1]" "D[2]" "D[3]" 00 00 00")
print d
for(i=1;i<=n;i++){
t+=86400
print strftime("%Y_%m_%d",t)
}
}'
output
$ ./shell.sh 2010_04_01 6
2010_04_01
2010_04_02
2010_04_03
2010_04_04
2010_04_05
2010_04_06
2010_04_07