hi I want to get the week number of the current month in bash, has someone an idea on how to do this? I search the date option, there is noting for week number only absolute week number.
WEEK => current week of month eg. today 22.05 WEEK=4
I found a few options, but there is no option, which works for every month and every date some give error if leading 0 some if month is even.
Here is a solution:
this_month=$(ncal -w | tail -1 | awk '{print NF}')
total_this_month=$(ncal -w | tail -1 | awk '{print $NF}')
this_week=$(date +%W)
this_monthweek=$(($this_week - $total_this_month + $this_month))
echo -e "today $(date +%d.%m) WEEK=$this_monthweek"
Hope, this is what you are looking for.
Edit:
A solution without ncal
this_month=$(date -d "20170501" +%V)
end_this_month=$(date -d "20170531" +%V)
total_this_month=$(($end_this_month - $this_month + 1))
this_week=$(date +%W)
this_monthweek=$(($this_week - $end_this_month + $total_this_month))
echo -e "today $(date +%d.%m) WEEK=$this_monthweek"
I found this solution working with AIX, but it works on any Unix
#!/bin/bash
year=$(date +'%Y')
month=$(date +'%m')
day=$(date +'%e' | tr -d '[:blank:]')
WEEKNUM=$(cal ${month} ${year} | grep -v "[[:alpha:]]" | grep -nw ${day} | cut -f1 -d':')
echo "WEEKNUM ${WEEKNUM}"
On Linux you can switch first day of the week to fit your needs
On AIX, first day of the week is inherited by locale
I figured something out, but I am not sure if it works for every month and week of the year, and I have not idea on how to manipulate the date to test it
current_week="$(date +%V)"
last_of_month="$(date --date "-"$(date +%d)" days +1 month" +%Y-%m-%d)"
last_of_month_week="$(date --date="${last_of_month}" +%V)"
week_number="$((${current_week} - ${last_of_month_week} + 5))"
Related
I have a file that consists of the following...
false|aaa|user|aaa001|2014-12-11|
false|bbb|user|bbb||
false|ccc|user|ccc|2021-10-19|
false|ddd|user|ddd|2018-11-16|
false|eee|user|eee|2020-06-02|
I want to use the date in the 5th column to calculate the number of days from the current date and append it to each line in the file.
The end result would be a file that looks like the following, assuming the current date is 1/13/2022...
false|aaa|user|aaa001|2014-12-11|2590
false|bbb|user|bbb||
false|ccc|user|ccc|2021-10-19|86
false|ddd|user|ddd|2018-11-16|1154
false|eee|user|eee|2020-06-02|590
Some lines in the file will not contain a date value (which is expected). I need a solution for a Bash script on Linux.
I am able to submit a command using echo for a single line and then calculate the number of days from the current date by using cut on the 5th field (see below)...
echo "false|aaa|user|aaa001|2014-12-11" | echo $(( ($(date --date=date +"%Y-%m-%d" +%s) - $(date --date=cut -d'|' -f5 +%s) )/(60*60*24) ))
2590
I don't know how to do this one line at a time, capture the 'number of days' value and then append it to each line in the file.
Here's an approach using
paste to append the outputs
sed to arrange the empty lines and
awk to calculate the desired days.
This works with GNU date. BSD date has to use something like date -jf x +%s.
EDIT: Updated the date to compare with to current day.
% current=$(date +%m/%d/%Y)
% paste -d"\0" file <(cut -d"|" -f5 file |
sed 's/^$/#/' |
xargs -Ix date -d x +%s 2>&1 |
awk -v cur="$(date -d "$current" +%s)" '/invalid/{print 0; next}
{print int((cur-$1)/3600/24)}')
false|aaa|user|aaa001|2014-12-11|2590
false|bbb|user|bbb||0
false|ccc|user|ccc|2021-10-19|86
false|ddd|user|ddd|2018-11-16|1154
false|eee|user|eee|2020-06-02|590
Also date returns date: invalid date ‘#’ in the empty case. If any other implementation behaves differently the awk regex has to be adjusted accordingly.
Data
% cat file
false|aaa|user|aaa001|2014-12-11|
false|bbb|user|bbb||
false|ccc|user|ccc|2021-10-19|
false|ddd|user|ddd|2018-11-16|
false|eee|user|eee|2020-06-02|
Trying to pull the last 5 minutes of logs with (grep matches)
so i do a tac syslog.log | sed / date -d "5 minutes ago"
every line on the log shows this format
Jun 14 14:03:58
Jul 3 08:04:35
so i really want to get the check of data from
Jul 4 08:12
Jul 4 08:17
i tried this method but KINDA works (though its still going through every day from this that 08:12: through 08:17: fits in)
e=""
for (( i = 5; i >= 0; i-- ))
do
e='-e /'`date +\%R -d "-$i min"`':/p '$e;
done
tac /var/log/syslog.log | sed -n $e
e=""
for (( i = 5; i >= 0; i-- ))
do
if [[ -z $e ]]
then e=`date +\%R -d "-$i min"`
else e=$e'\|'`date +\%R -d "-$i min"`
fi
done
re=' \('$e'\):'
tac /var/log/syslog.log | sed -n -e "/$re/p" -e "/$re/!q"
This creates a single regular expression listing all the times from the last 5 minutes, connected with \|. It prints the lines that matches them. Then it uses the ! modifier to quit on the first line that doesn't match the RE.
If you know the format of the dates then why not do:
tac syslog.log | awk '/Jul 4 08:17/,/Jul 4 08:12/ { print } /Jul 4 08:11/ {exit}'
/ .. /,/ .. / is regex range. It will print everything in this range. So as soon as you see /Jul 4 08:11/ on your line that would mean your 5 minutes window has been captured, you exit perusing the file.
So it didnt really work for the above method But i think i got it to work
if i see this i added a RANGE for the {exit}
awk '/'"$dtnow"'/,/'"$dt6min"'/ { print } /'"$dt7min"'/,/'"$dt11min"'/ {exit}'
Seems to work im testing it again
OK Finally looks like it really works this time (where it exits after the hour using SED instead of awk finally got it to work running through some tests.
tac /var/log/syslog.log | sed -e "$( date -d '-1 hour -6 minutes' '+/^%b %e %H:/q;'
date -d '-1 day -6 minutes' '+/^%b %e /q;'
date -d '-1 month -6 minutes' '+/^%b /q;'
for ((o=0;o<=5;o++)) do date -d "-$o minutes" '+/^%b %e %R:/p;'; done ; echo d)"
It works if log entries begins from "May 14 11:41". Variable LASTMINUTES is used to set the last n minutes in the log:
cat log | awk 'BEGIN{ LASTMINUTES=30; for (L=0;L<=LASTMINUTES;L++) TAB[strftime("%b %d %H:%M",systime()-L*60)] } { if (substr($0,0,12) in TAB) print $0 }'
To run the above script you need gawk which can be installed by:
apt-get install gawk
or
yum install gawk
in BASH I can't think of a good way to do this but I only want to see the past 30 days of entries in /var/log/messages*. The issue to me is how do I do that with just the Month and Day. For example:
Sep 2 14:26:13 <SOME ENTRY>
Sep 4 14:26:13 <SOME ENTRY>
Sep 9 14:26:13 <SOME ENTRY>
Sep 14 14:26:13 <SOME ENTRY>
etc..
Any ideas ? HELP! ha ha
I think this is close. This will give you a sorted list of entries (most recent first) through the start of August. Depending on when you run it, it will give you as much as ~60 days instead of 30. On average, I suppose it would give you about 45. The other downside is that you need to adjust the grep statement at the end of the pipe as the date advances.
sort -k1Mr -k2nr <file> | grep -E "Aug|Sep"
a little late but...
egrep "^$(date '+%b %e' -2d)" /var/log/messages
-- This works --- but ugly --
-- Print only the searches that meet the date in each loop iteration (i.e last X num days)
for (( i=0; i<=${MAXSEARCHDAYS}; i++)) ;do
egrep $(date --date "now -${i} days" +%b) ${USBFOUND} | grep $(date --date "now -${i} days" +%e) >> ${TEMPFILE}
done
sort -k1,1M -k2,2n ${TEMPFILE} | uniq >> ${LOGFILE}
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
How do you get the last day of the last month in csh?
Here is the code so far. The cal command below almost works if you execute it from the (FreeBSD sh) command line, but I'm having trouble escaping it properly to run within a script. By almost work, I mean it returns 31, when the last day of February 2010 is 28.
#!/bin/csh
set lastdayoflastmonth=`cal `date '+%m'` `date '+%Y'` | grep . | fmt -1 | tail -1`
echo $lastdayoflastmonth
To be clear:
If today is March 26th 2010, it should return the number 28, which is the last day of the February 2010.
If today is July 1st 2010, it should return the number 30, which is the last day of June 2010.
Update: working answer received from Joshua Smith in comments below: date -v31d -v-1m '+%d' Thank you!
Just use the date command:
date -v31d +'%a'
will give you the date name of the last day of the current month
for next month:
date -v31d -v+1m +'%a'
If you want the previous month:
date -v31d -v-1m +'%a'
-- EDIT: commenter has question about GNU Date ---
If you are using gnu date (the above uses BSD date) you can use the -d flag. It's a little more complicated, though (gnu date doesn't do the same thing with month length fuzziness). to get the last day of the month for last month
for the current month:
date -d "$(date -d "next month" +%Y-%m-1) -1 day" +%a
and for next month
date -d "$(date -d "2 months" +%Y-%m-1) -1 day" +%a
for last month:
date -d "$(date +%Y-%m-1) -1 day" +%a
I think (if I recall correctly) that you have to double the backticks (``) when 'nesting' them.
Try (untested):
set lastdayoflastmonth=`cal ``date '+%m'`` ``date '+%Y'`` | grep . | fmt -1 | tail -1`
echo $lastdayoflastmonth
you can shorten your command to omit the grep/fmt. also, there is no need to cram them into one line.
set month=`date '+%m'`
set year=`date '+%Y'`
set lastdaymonth=`cal $month $year |tr -s " " "\n"|tail -1`
eg
$ tcsh
$ set month="02"
$ set year="2010"
$ set lastdaymonth=`cal $month $year |tr -s " " "\n"|tail -1`
$ echo $lastdaymonth
28
$ tcsh --version
tcsh 6.17.00 (Astron) 2009-07-10 (i386-intel-linux) options wide,nls,dl,al,kan,rh,color,filec