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.
Related
I have a problem with a shell script. It is supposed to read arguments: index, date, time1 (the beginning of the interval), time2 (the end of the interval).
It should count how many times the user(index) has logged on the given date in the time interval time1-time2.
For example : 121212 "Jan 14" 00 12
This works, but I have a problem with the argument date. It doesn't recognize it as one argument. It splits it in Jan and 14" which is a big problem.
I've been searching on the internet for a few hours, but I couldn't find solution anywhere.
Here is my code:
#!/bin/bash
read user date time1 time2
list=`last | grep ^$user.*$date | awk '{ print $7 }'`
start=$time1
end=$time2
echo "start $start"
echo "end $end"
count=0
for el in $list ;
do
login=$el
echo "najava $najava"
checkIf(){
current=$login
[[ ($start = $current || $start < $current) && ($current = $end || $current < $end) ]]
}
if checkIf; then
count=`expr $count + 1`
ip=`last | grep ^$user.*$date.*$login | awk '{ print $3 }'`
echo $ip >> address.txt
else
continue
fi
done
echo "The user has logged in $count times in the given time interval"
From the man entry for read,
The characters in IFS are used to split the line into words.
And the default IFS on your system is likely the space. You can immediately fix your issue by escaping any spaces that you do not want to use as word separators:
121212 Jan\ 14 00 12
should work for your purposes.
But, of course, this is not an ideal solution. One possibility is to just pass your arguments to the script on the command line rather than through read after the script has been invoked, e.g.
#!/bin/bash
user="$1"
date="$2"
time1="$3"
time2="$4"
#etc
See http://www.shelldorado.com/goodcoding/cmdargs.html for more detail on handling command line arguments.
This question already has answers here:
Usage of :- (colon dash) in bash
(2 answers)
Closed 8 years ago.
The result is the one desired; after a bit of trial and error. I don't understand what the "2:-" and "3:-" do/mean. Can someone explain.
#!/bin/bash
pid=$(ps -ef | grep java | awk ' NR ==1 {print $2}')
count=${2:-30} # defaults to 30 times
delay=${3:-10} # defaults to 10 second
mkdir $(date +"%y%m%d")
folder=$(date +"%y%m%d")
while [ $count -gt 0 ]
do
jstack $pid >./"$folder"/jstack.$(date +%H%M%S.%N)
sleep $delay
let count--
echo -n "."
done
It's a parameter expansion, it means if the third argument is null or unset, replace it with what's after :-
$ x=
$ echo ${x:-1}
1
$ echo $x
$
There's also another similar PE that assign the value if the variable is null:
$ x=
$ echo ${x:=1}
1
$ echo $x
1
Check http://wiki.bash-hackers.org/syntax/pe
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.
This might be a bit strange. I have a string that indicates all of the "allowed" times per week. The String is 168 characters long. Each of the characters is either a 1 or a 0. Each character represents one hour of the week. So, the first 24 characters in the string indicate the "allowed" hours for Sunday. The next 24 characters are Monday and so on. The number 1 represents "allowed" and the number 0 represents not allowed. Here is a sample string:
000000111111111111111000000000111111111111111000000000111111111111111000000000111111111111111000000000111111111111111000000000111111111111111000000000111111111111111000
This string indicates allowed times between 6AM and 9PM Sunday through Saturday. Many times there will be different allowed hours for different days of the week. I'm trying to figure out it bash if the current day time is "allowed".
I've figured out that these tell me the current day and time:
DATE=$(date)
day=$(echo $DATE | cut -d' ' -f1)
time=$(echo $DATE | cut -d' ' -f4 | cut -d: -f1-2 | tr -d ':')
However, I can't figure out an elegant way of comparing those to my long string.
Any help would be greatly appreciated!
Please note: I am using BusyBox 1.19.4. That means that awk, sed, grep, etc may not be full-featured. :-(
EV
Here is another bash version which may help you. I am assuming that the input string is stored in a file and will be passed as an argument to the script :
i=`expr $(date +%w) \\* 24 + $(date +%H) + 1`
i=$(cat $1 | awk -v I=${i} '{print substr($0,I,1)}')
if [ $i -eq 1 ]
then echo "BUSY"
elif [ $i -eq 0 ]
then echo "FREE"
else
echo "error : input string is shorter than expected"
fi
If you want to pass the string as a parameter instead of a file, just replace the 'cat $1' part of the 2nd statement to :
echo $1
NB : In case input string is shorter than the i value, you will two error messages from shell "[: -eq: unary operator expected" for the two if conditions along with the 3rd echo statement. So you may want to improve the if conditions a bit.
Again, the above piece of code is valid only when the start of the week is Sunday 0th hour. Otherwise some other mapping must be used.
Interesting question!
Here is awk solution to do it in one shot. (without date stuff):
awk -v FIELDWIDTHS="24 24 24 24 24 24 24" '{split(strftime("%w,%H", systime()),t,",");for(i=0;i<7;i++)a[i]=$(i+1);print substr(a[t[1]],t[2]+1,1)?"OK":"NOK"}' file
for better reading:
awk -v FIELDWIDTHS="24 24 24 24 24 24 24" '{
split(strftime("%w,%H", systime()),t,",")
for(i=0;i<7;i++) a[i]=$(i+1)
print substr(a[t[1]],t[2]+1,1)?"OK":"NOK"
}' file
if I run this now, (here is Wed. 10:58 AM), it outputs:
OK
please test it with your real data, and report if it works. :)
Here is a bash only version
startoweek=`date +%s -d 20130717`
#1373999400
current=$(date +%s)
let diff=(${current}-${startoweek})/3600
if [ $diff -ge 168 ]
then echo "Old Timetable"
exit
fi
work=000000111111111111111000000000111111111111111000000000111111111111111000000000111111111111111000000000111111111111111000000000111111111111111000000000111111111111111000
allowed=${work:$diff:1}
if [ $allowed -eq 1 ]
then echo "Welcome"
elif [ $allowed -eq 0 ]
then echo "Go Home"
else
echo "Error"
fi
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