Iterate through 2 dates using bash script on mac - bash

I am trying to create a loop to iterate through 2 dates.
I have this so far, however it is going back in time. I want it to start with the start_date and end with the end_date.
I've tried to swap them around but it doesn't like that and adds +1day infinitely. Any help would be appreciated.
#!/usr/bin/env bash
end_date="21-12-21"
start_date="21-11-20"
# Set a counter variable
counter=0
#Increase the counter to get back in time
while [ "$end_date" != "$start_date" ]; do
end_date=$(date -v -${counter}d '+%y-%m-%d')
echo $end_date
counter=$((counter + 1))
done
This is what it produces
21-12-23
21-12-22
21-12-21
21-12-20
21-12-19
21-12-18
21-12-17
21-12-16
21-12-15
21-12-14
21-12-13
21-12-12
21-12-11
21-12-10
21-12-09
21-12-08
21-12-07
21-12-06
21-12-05
21-12-04
21-12-03
21-12-02
21-12-01
21-11-30
21-11-29
21-11-28
21-11-27
21-11-26
21-11-25
21-11-24
21-11-23
21-11-22
21-11-21
21-11-20
I'm also running this on a mac which seems to be quite fussy with the date formatting. This is the only way I have found it to work so far.

Related

Update global variable from while loop

Having trouble updating my global variable in this shell script.
I have read that the variables inside the loops run on a sub shell. Can someone clarify how this works and what steps I should take.
USER_NonRecursiveSum=0.0
while [ $lineCount -le $(($USER_Num)) ]
do
thisTime="$STimeDuration.$NTimeDuration"
USER_NonRecursiveSum=`echo "$USER_NonRecursiveSum + $thisTime" | bc`
done
That particular style of loop does not run in a sub-shell, it will update the variable just fine. You can see that in the following code, equivalent to yours other than adding things that you haven't included in the question:
USER_NonRecursiveSum=0
((USER_Num = 4)) # Add this to set loop limit.
((lineCount = 1)) # Add this to set loop control variable initial value.
while [ $lineCount -le $(($USER_Num)) ]
do
thisTime="1.2" # Modify this to provide specific thing to add.
USER_NonRecursiveSum=`echo "$USER_NonRecursiveSum + $thisTime" | bc`
(( lineCount += 1)) # Add this to limit loop.
done
echo ${USER_NonRecursiveSum} # Add this so we can see the final value.
That loop runs four times and adds 1.2 each time to the value starting at zero, and you can see it ends up as 4.8 after the loop is done.
While the echo command does run in a sub-shell, that's not an issue as the backticks explicitly capture the output from it and "deliver" it to the current shell.

Script with multiline string and for loop

Writing a quick script for a temporary/repetitive task. Wrote a basic solution that works:
for thing in "$#";
do
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id = $thing
END
done
This works but forces a password check for every member of argument array (not ideal).
Tried to update it to this:
if {$# -le 1}; then
for thing in "$#";
do
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id = $thing
END
done
else
things = ""
for thing in "$#";
do
things += "$thing"
if {$thing == $#[$# - 1]}; then
things += "\n"
continue
else
things += ",\n"
done
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id IN
(
$things
)
END
TLDR: If there is more than one argument: do a for loop to fill a WHERE .. IN () statement. I realize this doesn't even need to be a multiline string and maybe that is my issue but the error I'm getting is (apparently) unrealted .
The error I get is:
line 24: syntax error near unexpected token' done'
line 24: ' done'
Neither I, nor my supervisor have much experience with shell scripts but I cannot see any syntax error with the 2nd for loop. Its exactly the same as the first which executes fine.
Any help is greatly appreciated, I may just have to go to the basic version or write this as a Perl script instead. Thanks!
Thanks everyone for all the advice. This was an edit that worked:
#!/bin/sh
if [ $# -le 1 ]; then
for thing in "$#";
do
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id = $thing
END
done
else
things=""
i=1
for thing in "$#";
do
things+="$thing"
if [ $i -eq $# ]; then
things+=""
else
things+=", "
fi
((i+=1))
done
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id IN ($things)
END
fi
There were indeed many syntax errors and changing the WHERE .. IN () string construction to a single line made this a lot easier. Luckily I didn't have to worry about inserting single quotes, mysql took the query without them.
I came out of this with a much higher respect for bash scripting. It is a serious language that requires its own study and I will approach it with much more attention to detail in the future.
Thanks again.

Arithmetic operation on time variable in c-shell

I need help using time in the c-shell
I want to know how much time it took to execute a script,so i want to do in the following way
1.set start_time=time
2 script part
3.set end_time=time
4. set diff=end_time-start_time
5.echo "It took $diff seconds"
but i couldn't get the time value using any command.
could any one suggest a command to read the time value in c-shell
I think you want the "date" command, with the format to give you raw seconds:
# start_time = `date +%s`
script part
# end_time = `date +%s`
# diff = $end_time - $start_time
echo "It took $diff seconds"

C shell doing arithmetic operations with large numbers

First of all: sorry for using c shell, blame my company not me. I hate the damn thing as much as most of you do now (at first I was like, hey this ain't so bad).
I am trying to subtract large numbers obtained from time stamps. Here is what I am trying:
set curTime = `date +%s%N`
#... some stuff
#curTime = `date +%s%N` - $curTime #get the diff
echo "time taken: $curTime"
However I guess the numbers are too big - before I tried with just seconds and it worked fine. Here's what I see in the log:
#curMilli = 1349996279792995000 - 1349996279170458000
#curMilli: Command not found.
As I said I do the exact same thing with date +%s and it's fine, so I'm assuming it's something about the largeness of the numbers.
How can I do this? Thanks a lot.
The article http://en.wikipedia.org/wiki/Bc_programming_language has a short section "Using bc in shell scripts". A test:
set curTime = `/bin/date +%s%N`
/bin/sleep 2
set prevTime = $curTime
set curTime = `/bin/date +%s%N`
set diff = `echo "$curTime - $prevTime;" | /usr/bin/bc`
echo $diff
will give (with the digits after the initial 20 variable):
2016204108
P.s: I wish I could vote you up twice for "I hate the damn thing as much as most of you do now (at first I was like, hey this ain't so bad)."

Simple timer to measure seconds an operation took to complete

I run my own script to dump databases into files on a nightly basis.
I wanted to count time (in seconds) it takes to dump each database, so I was trying to write some functions to help me achieve it, but I'm running into problems.
I am no expert in scripting in bash, so if I'm doing it plain wrong, just say so and ideally suggest alternative, please.
Here's the script:
#!/bin/bash
declare -i time_start
function get_timestamp {
declare -i time_curr=`date -j -f "%a %b %d %T %Z %Y" "\`date\`" "+%s"`
echo "get_timestamp:" $time_curr
return $time_curr
}
function timer_start {
get_timestamp
time_start=$?
echo "timer_start:" $time_start
}
function timer_stop {
get_timestamp
declare -i time_curr=$?
echo "timer_stop:" $time_curr
declare -i time_diff=$time_curr-$time_start
return $time_diff
}
timer_start
sleep 3
timer_stop
echo $?
The code should really be quite self-explanatory. echo commands are only for debugging.
I expect the output to be something like this:
$ bash timer.sh
get_timestamp: 1285945972
timer_start: 1285945972
get_timestamp: 1285945975
timer_stop: 1285945975
3
Now this is not the case unfortunately. What I get is:
$ bash timer.sh
get_timestamp: 1285945972
timer_start: 116
get_timestamp: 1285945975
timer_stop: 119
3
As you can see, the value that local var time_curr gets from the command is a valid timestamp, but returning this value causes it to be changed to an integer between 0 and 255.
Can someone please explain to me why this is happening?
PS. This obviously is just my timer test script without any other logic.
UPDATE
Just to be perfectly clear, I want this to be part of a bash script very similar to this one, where I want to measure each loop cycle.
Unless of course I can do it with time, then please suggest a solution.
You don't need to do all this. Just run time <yourscript> in the shell.
$? is used to hold the exit status of a command and can only hold a value between 0 and 255. If you pass an exit code outside this range (say, in a C program calling exit(-1)), the shell will still receive a value in that range and set $? accordingly.
As a workaround, you could just set a different value in your bash function:
function get_timestamp {
declare -i time_curr=`date -j -f "%a %b %d %T %Z %Y" "\`date\`" "+%s"`
echo "get_timestamp:" $time_curr
get_timestamp_return_value=$time_curr
}
function timer_start {
get_timestamp
#time_start=$?
time_start=$get_timestamp_return_value
echo "timer_start:" $time_start
}
...
I believe you should be able to use the existing "time" function.
After Update to the question:
This was the bit of script from your link which was doing a for loop.
# dump each database in turn
for db in $databases; do
echo $db
$MYSQLDUMP --force --opt --user=$USER --password=$PASSWORD
--databases $db > "$OUTPUTDIR/$db.bak"
done
You could extract the inner portion of the loop into a new script (call it dump_one_db.sh)
and do this inside the loop:
# dump each database in turn
for db in $databases; do
time dump_one_db.sh $db
done
Make sure to write the output of the time against the db name into some file.
This is happening because return codes need to be between 0-255. You can't return an arbitrary number. If you continue to refuse to use the builtin time function and roll your own, change your functions to echo their stamp and use a process expansion ($()) to grab the value.

Resources