I have a problem to create a script. My problem is when trying to subtract a date. In my script I pass a date with the format dd/mm/yyyy as parameter and I need to compare with files in a directory that has the date in the filename. The date can be the actul or until 5 days before the day passed as parameter. My question is, how can I create an if condition for example that will compare the date as parameter and the last 5 days before it with the date that is specified in the filename ? I already searched in every place how can I do it and nothing could help me.
Thanks for now.
Jairo.
Not sure of your requirement, but this may help you(not the best of solutions)
assuming the file names are in format: file_11092013 , file_01092013
#!/bin/bash
PASSED_DATE=$1
date_diff() {
d1=$(date -d "$1" +%s)
d2=$(date -d "$2" +%s)
echo $(( (d2 - d1) / 86400 ))
}
for file in `ls /home/mvaidya/test`
do
curr_file=`echo $file | awk 'BEGIN {FS="_"} {print $NF}'`
day1=`echo $curr_file| cut -c1-2`
month1=`echo $curr_file| cut -c3-4`
year1=`echo $curr_file| cut -c5-8`
day2=`echo $PASSED_DATE| cut -c1-2`
month2=`echo $PASSED_DATE| cut -c4-5`
year2=`echo $PASSED_DATE| cut -c7-10`
no_of_days=$( date_diff "$month2/$day2/$year2" "$month1/$day1/$year1" )
if [ $no_of_days -ge 5 ] ; then
echo "File "$file" more than 5 days old."
else
echo "File "$file" less than 5 days old."
fi
done
Eg:
$./exp1.sh 01/09/2013
File file_11092013 more than 5 days old.
$./exp1.sh 10/09/2013
File file_11092013 less than 5 days old.
Related
This question already has answers here:
How to read variables from file, with multiple variables per line?
(2 answers)
Closed last month.
I have stuck in subtrack from file using shell script, below my data. this file name is age
1673495825 1673420702 01/11/23_14:05:02
1673495825 1673420702 01/11/23_14:05:02
My expectation is collum 1 will be subtrack with collum 2
here my code
for i in "$(cat age)"
do
timestamp="$(echo "$i" | sed 's/ .*//' | awk '$1=$1')"
firstoccure="$(echo "$i" | awk '{print $2}' | awk '$1=$1')"
aging="$((timestamp - firstoccure))"
if [ $aging -gt 43200 -o $aging -lt 86400 ]
then
echo "12 Hours"
elif [ $aging -gt 86400 ]
then
echo "24 Hours"
fi
done
whit above script I have an error like this
***1673495776: syntax error in expression (error token is "1673495776")***
if my list only 1, the script will be success.
need your help
thanks
Expect I can solve th problem
for i in "$(cat age)" iterates only once with i equal to the whole content of the age file. Probably not what you want.
The following does everything with awk:
awk '{
a=$1-$2;
if(a>43200 && a<86400)
print "12 Hours";
else if(a>86400)
print "24 Hours"
}' age
If you really prefer using bash, you can try:
while read -r timestamp firstoccure dummy; do
((aging=timestamp-firstoccure))
if ((aging>43200)) && ((aging<86400)); then
echo "12 Hours"
elif ((aging>86400)); then
echo "24 Hours"
fi
done < age
Note: with your inequalities if aging=86400 nothing will be printed.
This question already has answers here:
Date comparison in Bash [duplicate]
(2 answers)
Closed 1 year ago.
I would like to compare line number 13 in two different files. That line contains date in the format: "Nov 8 00:46:57 2021 GMT"
I want to compare these two dates, and check which is less or greater than the other. Can someone please help me with this.
# Reads line 13 of file1.txt into date1
date1=$(awk 'NR==13' file1.txt)
# Reads line 13 of file2.txt into date2
date2=$(awk 'NR==13' file2.txt)
# converts date to seconds since the Epoch in Linux
date1=$(date -d "$date1" +%s)
date2=$(date -d "$date2" +%s)
if (( date1 >= date2 )); then
echo "Date in file1.txt is greater or equal"
else
echo "Date in file2.txt is greater"
fi
13a and 13b are your file names:
iso8601-13() {
date -d "`head -13 "$1" | tail -n 1`" --iso-8601=seconds
}
if [[ `iso8601-13 13a` < `iso8601-13 13b` ]] ; then
echo 13a is earlier
fi
In bash on macOS, I would like to write a small script with dates (or any other program that would do) that gives me a list of dates in the format yyyymmdd of every Saturday of a given year and saves it to a variable.
For example, if I wanted to have a list of dates for all Saturdays of the year 1850, it should somehow look like this:
var = [ 18500105, 18500112, 18500119, …, 18501228 ]
with the below code:
list=()
for month in `seq -w 1 12`; do
for day in `seq -w 1 31`; do
list=( $(gdate -d "1850$month$day" '+%A %Y%m%d' | grep 'Saturday' | egrep -o '[[:digit:]]{4}[[:digit:]]{2}[[:digit:]]{2}' | tee /dev/tty) )
done
done
However, the above command does not write anything in the array list although it gives me the right output with tee.
How can I fix these issues?
Modifying Dennis Williamson's answer slightly to suit your requirement and to add the results into the array. Works on the GNU date and not on FreeBSD's version.
#!/usr/bin/env bash
y=1850
for d in {0..6}
do
# Identify the first day of the year that is a Saturday and break out of
# the loop
if (( $(date -d "$y-1-1 + $d day" '+%u') == 6))
then
break
fi
done
array=()
# Loop until the last day of the year, increment 7 days at a
# time and append the results to the array
for ((w = d; w <= $(date -d "$y-12-31" '+%j'); w += 7))
do
array+=( $(date -d "$y-1-1 + $w day" '+%Y%m%d') )
done
Now you can just print the results as
printf '%s\n' "${array[#]}"
To set up the GNU date on MacOS you need to do brew install coreutils and access the command as gdate to distinguish it from the native version provided.
Argh, just realised you need it for MacOS date.
I will leave the answer for others that do not have that restriction, but it will not work for you.
This is not quite what you want, but close:
year=1850
firstsat=$(date -d $year-01-01-$(date -d $year-01-01 +%w)days+6days +%Y%m%d)
parset a 'date -d '$firstsat'+{=$_*=7=}days +%Y%m%d' ::: {0..52}
echo ${a[#]}
It has the bug, that it finds the next 53 Saturdays, and the last of those may not be in current year.
parset is part of GNU Parallel.
I didn't do much error checking, but here's another implementation.
Takes day of week and target year as arguments.
Gets the julian day of the first matching weekday requested -
gets the epoch seconds of noon on that day -
as long as the year matches what was requested, adds that date to the array and adds a week's worth of seconds to the tracking variable.
Lather, rinse, repeat until no longer in that year.
$: typeset -f alldays
alldays () { local dow=$1 year=$2 julian=1;
until [[ "$dow" == "$( date +%a -d $year-01-0$julian )" ]]; do (( julian++ )); done;
es=$( date +%s -d "12pm $year-01-0$julian" );
allhits=( $( while [[ $year == "$( date +%Y -d #$es )" ]]; do date +%Y%m%d -d #$es; (( es+=604800 )); done; ) )
}
$: time alldays Sat 1850
real 0m9.931s
user 0m1.025s
sys 0m6.695s
$: printf "%s\n" "${allhits[#]}"
18500105
18500112
18500119
18500126
18500202
18500209
18500216
18500223
18500302
18500309
18500316
18500323
18500330
18500406
18500413
18500420
18500427
18500504
18500511
18500518
18500525
18500601
18500608
18500615
18500622
18500629
18500706
18500713
18500720
18500727
18500803
18500810
18500817
18500824
18500831
18500907
18500914
18500921
18500928
18501005
18501012
18501019
18501026
18501102
18501109
18501116
18501123
18501130
18501207
18501214
18501221
18501228
I am writing a bash script which will print the number of weeks,days and hours left for user's birthday from the time it is run. The user will only fill in the his birth-date and month.
I searched and found out that we can take difference of two dates:
let DIFF=(`date +%s -d 20150108`-`date +%s -d today`)/86400
echo $DIFF
The above script will print the number of days left for the given date. We can similarly find out the number of weeks and hours.
But the problem is, if user gives only the birth-date excluding the year, (here he gives only 8 Jan) how do I figure out the least difference possible between upcoming birthday and today?
Example, if the birthday just passed , then I have to consider the birthday which comes next year.
Just check if the date happened already this year, and if it did append next year to the input.
> input="8 Feb"
> input=$(date -d "$input" '+%d %b')
> [[ $(date -d "$input" '+%s') -lt $(date -d "$(date '+%d/%m/%y')" '+%s') ]] && input="$input $(( $(date '+%Y') + 1 ))"
> let DIFF=(`date +%s -d "$input"`-`date +%s -d today`)/86400
> echo $DIFF
360
Couple of caveats. 2nd line strips year and other information (time, etc...) from date if user enters it with that. And $(date -d "$(date '+%d/%m/%y')" '+%s') in third line is needed so it compares only against the current date, rather than the date with time.
Another way to count days is to use date's %j format code, which returns the day number in the year (an three-digit integer between 001 and 366, inclusive). (Note: we prepend 1 to the output of date +%j to make it a four-digit integer not starting with a 0, to avoid octal conversion.)
DATE="Feb 7"
TODAY=1$(date +%j)
BDAY=1$(date +%j -d "$DATE")
if ((BDAY<TODAY)); then
BDAY=1$(date +%j -d "$DATE "$(($(date +%Y)+1)))
fi
DAYS_TO_GO=$(($BDAY-$TODAY))
This question already has answers here:
How can I calculate time elapsed in a Bash script?
(20 answers)
Closed 5 years ago.
I'm trying to compare a date given by a user to a date in a file, basically a text file with lots of dates and times listed.
for example the user would enter a date such as 22/08/2007 and a time of 1:00, what i need the script to do is count how many dates in the text file are after the date given by the user.
I’ve managed to accomplish this by converting each date in the text file to unix timestamp and then comparing the two. Is there no way of simply comparing two dates in bash?
Thanks in advance
The GNU date command can convert a date into the number of seconds since 1970. Try this script:
#! /bin/bash
DATE=$(date -d "$3-$2-$1 01" '+%s')
COUNT=0
tr '/' ' ' | {
while read D M Y ; do
THIS=$(date -d "$Y-$M-$D 01" '+%s')
if (( THIS > DATE )) ; then
COUNT=$((COUNT + 1))
fi
done
echo $COUNT
}
It expects three arguments and the raw dates in stdin:
for D in $(seq 19 25) ; do echo $D/08/2007 ; done | ./count.sh 22 08 2007
3
It will work till 2038. ;-)
If you don't mind an external helper tool look at my dateutils. Your use case is covered by
dgrep -i '%d/%m/%Y %H:%M' '>=2007-08-22 01:00:00' < FILE | wc -l
where FILE is your file with the dates, and -i specifies the date format used in the file (I assumed dates like 22/08/2007 01:00 here). Matching lines will be printed, hence counting them gives you the information you were after.
...why don't you simply cut out the single numbers, rearrange them from the most signifcant to the less significant, put them toghether to form a new big number and then compare the other one? :) Suppose you have a date in both $1 and $2 and suppose the date format is dd-mm-yyyy (adding hours and minutes is trivial):
d1=`echo "$1" | cut -d "-" -f 1`
m1=`echo "$1" | cut -d "-" -f 2`
y1=`echo "$1" | cut -d "-" -f 3`
date1="$y1$m1$d1"
d2=`echo "$2" | cut -d "-" -f 1`
m2=`echo "$2" | cut -d "-" -f 2`
y2=`echo "$2" | cut -d "-" -f 3`
date2="$y2$m2$d2"
if [ "$date1" -gt "$date2" ]; then
#date1 > date2
else
#date2 >= date1
fi
Note that you need zeros for 1-digit fields, for example, dates like this will work:
01-01-2013
and dates like this will NOT
1-1-2013
Cheers :-)
The problem is that dates are printed in such a way that, string-wise, "1/1/2050 1:00" < "2/1/1999 0:00". And since there's no way for a script to know that something is a datetime without you saying so, you essentially have to convert any date to something that can be compared - Either you have to order the elements so that the most important (year) are first, etc. (like ISO dates) or you convert to a number.
the above command compares the date in form of integer and would work fine until you are comparing the dates of same year.
better idea is to break the dates into 3 parts of dd, mm and yyyy and then do a comparison. just as below:
sysdate=`date +%d%m%Y`
sys_dd=`echo $sysdate|cut -c1,2`
sys_mm=`echo $sysdate|cut -c3,4`
sys_yyyy=`echo $sysdate|cut -c5-8`
cd $dir_source #moving in directory where report are placed
for i in *.* #reading all the files present in directory and comparing with current sysdate
do
filename=$i
filedate=`echo $filename| cut -d '_' -f1`
file_dd=`echo $filedate|cut -c1,2`
file_mm=`echo $filedate|cut -c3,4`
file_yyyy=`echo $filedate|cut -c5-8`
if [ $sys_yyyy -lt $file_yyyy ]
then
echo "future cob file, check for the error"elif [ $sys_yyyy -gt $file_yyyy ]
then
echo "prev cob file , to be removed"
else
if [ $sys_mm -lt $file_mm ]
then
echo "future cob file, check for the error"
elif [ $sys_mm -gt $file_mm ]
then
echo "prev cob file , to be removed"
else
if [ $sys_dd -lt $file_dd ]
then
echo "future cob file, check for the error"
elif [ $sys_dd -gt $file_dd ]
then
echo "prev cob file , to be removed"
else
echo "file date is same is cob date, retaining the file as it is"
fi
fi
fi