Error on backup bash script: syntax error near unexpected token `newline' - bash

I am having problem finding error on bash script for handling backup:daily, monthly, yearly. Here is the script:
#!/bin/bash
echo > /home/alpha/folder/keep.txt
#writing dates of the backups that should be kept to the array
for i in {0..7}; do ((keep[$(date +%Y%m%d -d "-$i day")]++)); done
for i in {0..4}; do ((keep[$(date +%Y%m%d -d "sunday-$((i+1)) week")]++)); done
for i in {0..12}; do
DW=$(($(date +%-W)-$(date -d $(date -d "$(date +%Y-%m-15) -$i month" +%Y-%m-01) +%-W)))
for (( AY=$(date -d "$(date +%Y-%m-15) -$i month" +%Y); AY < $(date +%Y); AY++ )); do
((DW+=$(date -d $AY-12-31 +%W)))
done
((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++))
done
for i in {0..30}; do
DW=$(date +%-W)
for (( AY=$(($(date +%Y)-i)); AY < $(date +%Y); AY++ )); do
((DW+=$(date -d $AY-12-31 +%W)))
done
((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++))
done
#writing the array to file keep.txt line by line
for i in ${!keep[#]}; do echo $i >> /home/alpha/folder/keep.txt; done
#delete all files that not mentioned in keep.txt
cd /home/alpha/folder
ls -1 /home/alpha/folder/ | sort /home/alpha/folder/keep.txt /home/alpha/folder/keep.txt - | uniq -u | xargs rm -rf
rm /home/alpha/folder/keep.txt
When I try to run the script, throws error message:
./back.sh: line 12: syntax error near unexpected token `newline' ./back.sh: line 12: ` done'
Where did I do wrong on the script?

Your date expression seems to misbehave inside the arithmetic context. Adding temporary variables solved your issue for me :
#!/bin/bash
echo > /home/alpha/folder/keep.txt
#writing dates of the backups that should be kept to the array
for i in {0..7}; do ((keep[$(date +%Y%m%d -d "-$i day")]++)); done
for i in {0..4}; do ((keep[$(date +%Y%m%d -d "sunday-$((i+1)) week")]++)); done
for i in {0..12}; do
DW=$(($(date +%-W)-$(date -d $(date -d "$(date +%Y-%m-15) -$i month" +%Y-%m-01) +%-W)))
begin=$(date -d "$(date +%Y-%m-15) -$i month" +%Y)
for (( AY=begin; AY < $(date +%Y); AY++ )); do
((DW+=$(date -d $AY-12-31 +%W)))
done
((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++))
done
for i in {0..30}; do
DW=$(date +%-W)
begin=$(($(date +%Y)-i))
for (( AY=begin; AY < $(date +%Y); AY++ )); do
((DW+=$(date -d $AY-12-31 +%W)))
done
((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++))
done
#writing the array to file keep.txt line by line
for i in ${!keep[#]}; do echo $i >> /home/alpha/folder/keep.txt; done
#delete all files that not mentioned in keep.txt
cd /home/alpha/folder
ls -1 /home/alpha/folder/ | sort /home/alpha/folder/keep.txt /home/alpha/folder/keep.txt - | uniq -u | xargs rm -rf
rm /home/alpha/folder/keep.txt
However, I am unsure why the expression misbehaves inside the arithmetic block.

Related

How to subtract today's date with a file's modification date in unix?

For example:
echo $(date) - $(date -r sample.txt)
Output:
90 days(for example)
Use %s seconds since 1970-01-01 00:00:00 UTC as in
echo $(expr $(date +%s) - $(date -r sample.txt +%s)) #!/bin/sh
echo $(($(date +%s) - $(date -r sample.txt +%s))) #/bin/bash
One more way
$ ls -l peter.txt
-rwxrw-r--+ 1 pppp qqqq 149 Dec 15 18:39 peter.txt
$ echo "(" $(date +%s) - $(date -r peter.txt +%s) ")/" 86400 | perl -nle ' print eval, " days" '
29.254537037037 days
$

date bash script works under RHEL but not ubuntu

the script from How to keep: daily backups for a week, weekly for a month, monthly for a year, and yearly after that
works under RHEL7 but reports errors when used on two separate ubuntu machines
I do not find what could be wrong with it besides it has loops within loops and some expressions are not quoted
keepdates ()
{
for i in {0..7};
do
((keep[$(date +%Y%m%d -d "-$i day")]++));
done;
for i in {0..4};
do
((keep[$(date +%Y%m%d -d "sunday-$((i+1)) week")]++));
done;
for i in {0..12};
do
DW=$(($(date +%-W)-$(date -d $(date -d "$(date +%Y-%m-15) -$i month" +%Y-%m-01) +%-W)));
for ((AY=$(date -d "$(date +%Y-%m-15) -$i month" +%Y); AY < $(date +%Y); AY++ ))
do
((DW+=$(date -d $AY-12-31 +%W)));
done;
((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++));
done;
for i in {0..5};
do
DW=$(date +%-W);
for ((AY=$(($(date +%Y)-i)); AY < $(date +%Y); AY++ ))
do
((DW+=$(date -d $AY-12-31 +%W)));
done;
((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++));
done;
echo ${!keep[#]}
}
The error is:
-bash: ./test.sh: line 18: syntax error near unexpected token `newline'
-bash: ./test.sh: line 18: ` done;'
any idea?
added output under RHEL7
$ bash --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ date --version
date (GNU coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by David MacKenzie.
$ keepdates; # my custom function but a bash script would do the same
20130106 20140105 20150104 20160103 20170101 20170205 20170305 20170402 20170507 20170604 20170702 20170806 20170903 20171001 20171105 20171203 20171224 20171231 20180107 20180114 20180117 20180118 20180119 20180120 20180121 20180122 20180123 20180124
(I have no fedora but openSUSE 42.3 with GNU bash, Version 4.3.42(1)-release.)
The unnecessary semicolons have already been mentioned above. You call the date command with a fix result in your loops.
I wrote sequencies with $(seq from to) but that's just cosmetics, the {1..3} notation works too, I did not know that before.
The main problem is the nested date call in line 13 and the date call within the double expression evaluation in line 23 of your original post.
I have solved that by pulling out the fixed variables motm (MiddleOfTheMonth) and EY (EndYear).
For Line 13:
in this for condition $(date +%Y-%m-15) is fixed, why should the value be recalculated every time, same for $(date +%Y), try this line alone:
i=5; for ((AY=$(date -d "$(date +%Y-%m-15) -$i month" +%Y); AY < $(date +%Y); AY++ )); do echo $AY; done
-bash: syntax error near unexpected token `newline'
and with the $mdtm:
motm="2018-01-15"; i=5; for ((AY=$(date -d "$motm -$i month" +%Y); AY < $(date +%Y); AY++ )); do echo $AY; done
2017
For Line 23 you can observe the for condition:
i=2; for ((AY=$(($(date +%Y)-i));AY<2018;AY++));do echo $AY; done
-bash: syntax error near unexpected token `newline'
and
i=2; for ((AY=$((2018-i));AY<2018;AY++));do echo $AY; done
2016
2017
I do not know what goes wrong in the bash. I can only tell you how to write it down so it works.
This one produce the same on openSUSE and Ubuntu 16.04.3 LTS
#!/bin/bash
keepdates ()
{
local -a keep
for i in $(seq 0 7)
do
(( keep[$(date +%Y%m%d -d "-$i day")]++ ))
done
for i in $(seq 0 4)
do
(( keep[$(date +%Y%m%d -d "sunday-$((i+1)) week")]++ ))
done
motm=$(date +%Y-%m-15)
for i in $(seq 0 12)
do
DW=$(( $(date +%-W)-$(date -d $(date -d "$motm -$i month" +%Y-%m-01) +%-W) ))
for (( AY=$(date -d "$motm -$i month" +%Y); $AY < $(date +%Y); AY++ ))
do
(( DW+=$(date -d $AY-12-31 +%W) ))
done
(( keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++ ))
done
for i in $(seq 0 5)
do
DW=$(date +%-W)
EY=$(date +%Y)
for (( AY=$(( EY-i )); $AY < $EY; AY++ ))
do
(( DW+=$(date -d $AY-12-31 +%W) ))
done
(( keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++ ))
done
echo ${!keep[#]}
}
keepdates

How to use DATE command with an external variable?

I'm working on a time convertion script. It is supposed to do something like this:
echo $(( ($(date -d '00:10:2.00' +%s) - $(date -d 0 +%s) ) ))
This line is working just fine giving me the result
602
But I want to put the the first part of the date string (00:10:2.00) under a) an command line argument so it could be read from $1 like:
echo $(( ($(date -d '$1' +%s) - $(date -d 0 +%s) ) ))
OR as a variable:
echo $(( ($(date -d '$myvariable' +%s) - $(date -d 0 +%s) ) ))
When I'm trying this:
foo="00:10:2.00"
echo $foo
echo $(( ($(date -d '$foo' +%s) - $(date -d 0 +%s) ) ))
All I get is:
00:10:2.00
date: invalid date `$foo'
-1417042800
So it's echoing properly but it aint working with the time command...
Variables are expanded inside double quotes, they're not expanded inside single quotes. So use
date -d "$1" +%s

How to compare the current date with past 60 days using shell script

start_time=`sed -e 's/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\).*/\1/' <<< "$line"`
start_time_sec=`date -d "$start_time" +%s`
now=`date +%s`
pass_time=`$now - $start_time_sec`
if [ $pass_time <=86400*60 ]
then
initial_time= $start_time
initial_time_sec=`date -d "$initial_time" +%s`
break
fi
/Here I have tried with date comparison with seconds, But I want in terms of days/
ISO dates (YYYY-MM-DD) can be compared like strings:
$ date +%Y-%m-%d
2014-01-07
$ date +%Y-%m-%d -d '-60 days'
2013-11-08
$ [[ "$(date +%Y-%m-%d -d '-60 days')" < "$(date +%Y-%m-%d)" ]]
$ echo $?
0
start_time=`echo $line | sed -e 's/^\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\).*/\1/'`
start_time_sec=`date -d "$start_time" +%s`
now=`date +%s`
pass_time=`expr $now - $start_time_sec`
limit_time=$((60 * 60 * 24 * 60))
if [[ $pass_time -le $limit_time ]]; then
echo "in 60 days"
fi
update:
or your idea:
start_time_date=`date -d "$start_time" +%s`
past_date=`date +"%Y-%m-%d" -d "-60 day"`
if [[ $past_date -le $start_time_date ]]; then
echo 'in 60 days'
fi

How to read a file content using shell script

cat file.txt
(
while read line
do
initial_time=`head -n 1 $line| sed -e 's/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\).*/\1/'`
initial_time_sec=`date -d "$initial_time" +%s`
done
)
I want to take the date from every line , if it is less than 60 days I have to store it in variable
while read line ; do
initial_time=`echo $line | sed -e 's/.*\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\).*/\1/'`
initial_time_sec=`date -d "$initial_time" +%s`
now=`date +%s`
pass_time=`expr $now - $initial_time_sec`
limit_time=$((60 * 24 * 60))
if [[ $pass_time -lt $limit_time ]]; then
echo $line
fi
done <data

Resources