Subtracting number from bash variable - command not found - bash

I am new to bash. I tried to find the answer to this, but couldn't quite find the solution. I am trying to subtract 86400 from $yesterday_date, but I end up with a "command not found" error.
(I know there are other methods of subtracting from a date, but I still want the solution to this problem.)
Script section:
yesterday_date=$(date +%s)
echo $yesterday_date
yesterday_date=$($yesterday_date-86400)
echo $yesterday_date
Script output:
1517335264
./myscript.sh: line 11: 1517335264-86400: command not found
What's the problem? Thanks.

Bash provides ((...)) for arithmetic operations. You don't have to use $ before ((..)).
yesterday_date=$(date +%s)
echo "$yesterday_date"
((yesterday_date-=86400))
echo "$yesterday_date"

You can let date do the math:
echo $(date -d "now -86400 seconds" +%s)
1517268350
or elimninate the magic number:
echo $(date -d "now -1 day" +%s)
1517268356
or even more literal:
echo $(date -d "yesterday" +%s)
1517268364
For fun, there is even a teatime option to the date command. ;)

Related

Couldn't figure out the error at printing custom timestamp in shell script using date?

I am trying to manipulate timestamps using date in shell script. My code is this
echo $(date -d '+10 mins' +%s%N)
This will print time 10 mins from current time in nanoseconds
1554242194228787268
When i move the echo statement inside a for loop to do a custom action based on the loop variable.
for repi in `seq 1 2`;
do
lp_incr=$((repi*10))
n_incr='+'$lp_incr' mins'
echo $(date -d $n_incr +%s%N)
done
Getting error like this
date: extra operand '+%s%N'
Remove that extra operand won't help me to view date alone
for repi in `seq 1 2`;
do
lp_incr=$((repi*10))
n_incr='+'$lp_incr' mins'
echo $n_incr
echo $(date -d $n_incr)
done
Again getting different error
+10 mins
date: the argument 'mins' lacks a leading '+';
$n_incr have the '+'still it throws an error.
It seems like i miss something in this. Entire motive is generate timestamp in nano seconds for some interval.
Thanks in advance for all suggestions or alternate approaches.
In
echo $(date -d $n_incr +%s%N)
$n_incr is expanded to
echo $(date -d +10 mins +%s%N)
Note that +10 mins is not a single argument, but two.
The fix is to quote the argument:
echo $(date -d "$n_incr" +%s%N)
You can also omit $n_incr:
echo $(date -d "+$lp_incr mins" +%s%N)

Use different variables in one while loop or better use for loop? [duplicate]

This question already has answers here:
A variable modified inside a while loop is not remembered
(8 answers)
Closed 4 years ago.
please bear with me and my questions, but I just started programming in bash yesterday effectively.
I have a script that does a lot of stuff so far. And I came to a point where I need to iterate through variables. I created these variables before using a while loop. The $Time variable for example looks like this:
2016-01-29 17:07:00Z
2016-01-29 17:26:20Z
2016-01-29 17:26:20Z
2016-01-29 00:07:00Z
The Grabinterval variable like this:
hour
minute
minute
day
The first step for me is to check if a different variable is not empty. If it is not I go on with checking line per line inside the $Grabinterval variable what kind it is day, hour or minute.
That is done by a while loop as well and works good. But no the problems are rising. Now I want to calculate a time difference between a time that was created earlier outside of the while loop and the time given in the first line of the $Time variable. I tried this using the following code:
while read -r line; do
if [[ ! -z "$Filelocation" ]]
then
if [[ $line = "day" || $line = "days" ]]
then
Interval="Days"
GrabTimeNew=$(date +'%Y-%m-%d 00:0'$UPOFFSET':00Z')
default=$(date --date "-1 day" +'%Y-%m-%d 00:0'$UPOFFSET':00Z')
start=$(date -d"$line$Time" +%s)
end=$(date -d"$GRABtime" +%s)
TimeDiff=$(( $start - $end ))
fi
fi
done <<< $Grabinterval
This is only on part of the bigger while loop, the other two parts looking for hour and minuteare pretty much the same.
The way I tried it here using $line$Time gives me following error message:
date: invalid date ‘day2016-01-29 17:07:00Z\n2016-01-29 17:26:20Z\n2016-01-29 17:26:20Z\n2016-01-29 00:07:00Z’
So it goes over all lines instead of only the dayline I want it to go through. Is there a way to use the first line of the $Timevariable inside the $Grabinterval variable?
I would love to use a for loop, but I have no idea how to use it later in the command block to have the wanted line read in the command block of the if statement.
Thanks,
BallerNacken
EDIT: Tried something like this now, but not working either:
while read -r GI TI; do
if [[ ! -z "$Filelocation" ]]
then
if [[ $GI = "day" || $GI = "days" ]]
then
Interval="Days"
GrabTimeNew=$(date +'%Y-%m-%d 00:0'$UPOFFSET':00Z')
default=$(date --date "-1 day" +'%Y-%m-%d 00:0'$UPOFFSET':00Z')
start=$(date -d"$TI" +%s)
end=$(date -d"$GRABtime" +%s)
TimeDiff=$(( $start - $end ))
fi
if [[ $GI = "hours" || $GI = "hour" ]]
then
Interval="Hours"
GrabTimeNew=$(date +'%Y-%m-%d %H:0'$UPOFFSET':00Z')
default=$(date --date "-1 hour" +'%Y-%m-%d %H:0'$UPOFFSET':00Z')
start=$(date -d"$TI" +%s)
end=$(date -d"$GRABtime" +%s)
TimeDiff2=$(( $start - $end ))
fi
if [[ $GI = "min" || $GI = "minutes" || $GI = "minute" ]]
then
Interval="Minutes"
GrabTimeNew=$(date +'%Y-%m-%d %H:%M:20Z')
default=$(date --date "-1 minute" +'%Y-%m-%d %H:%M:00Z')
start=$(date -d"$TI" +%s)
end=$(date -d"$GRABtime" +%s)
TimeDiff3=$(( $start - $end ))
fi
fi
done < <(paste <(echo "$Grabinterval") <(echo "$Time"))
I don't get any error messages, but no variables were created inside the if statement/while loop.
You might want to try something like this:
while read -r interval datetime; do
#...
done < <(paste <(echo "$Grabinterval") <(echo "$Time"))
That will read one line from Grabinterval and the corresponding line from Time
You need to quote the variable to keep the newlines in the <<< $var.
list=$'a\nb\nc'
while read a ; do echo $a ; done <<< $list
while read a ; do echo $a ; done <<< "$list"

command date script shell bsh/ksh

I need help.
I made a shell script that you pass a date earlier than 3 days in YYYYMMDD format and tell me if it is correct or not.
My question is. Can i subtract the date command 3 days?
thanks.
you can test :
DATE="20120803"
date -d #$(( `date -d "$DATE" +%s` - (3*24*60*60) ))
for the fancy solution:
INPUT="20120803"
INPUT_SECONDS=$(date -d "$INPUT" +%s)
THREEDAYSAGO_SECONDS=$(date -d "3 days ago" "+%s")
if [ $INPUT_SECONDS -lt $THREEDAYSAGO_SECONDS ]; then
echo "too early :("
fi
Although you can use the date command to do this (see Guillame's excellent answer) it may be worth considering a scripting language such as Perl to do more complex stuff more efficiently.
e.g. see this SO answer, using Perl and the DateTime.pm module:
use DateTime;
my $date = DateTime->now;
$date->subtract(days => 3);
print $date->ymd;

Combine two shell commands into one output in shell

I am trying to combine multiple commands into a single output.
#!/bin/bash
x=$(date +%Y)
x=$($x date +m%)
echo "$x"
This returns
./test.sh: line 4: 2011: command not found
x=$(echo $(date +%Y) $(date +%m))
(Note that you've transposed the characters % and m in the month format.)
In the second line, you're trying to execute $x date +m%. At this point, $x will be set to the year, 2011. So now it's trying to run this command:
2011 date +%m
Which is not what you want.
You could either do this:
x=$(date +%Y)
y=$(date +%m)
echo "$x $y"
Or that:
x=$(date +%Y)
x="$x $(date +%m)"
echo "$x"
Or simply use the final date format straight away:
x=$(date "+%Y %m")
echo $x
Maybe this?
#!/bin/bash
x=$(date +%Y)
x="$x$(date +%m)"
echo "$x"
...also correcting what appears to be a transpose in the format string you passed to date the second time around.
Semicolon to separate commands on the command line.
date +%Y ; date +m%
Or if you only want to run the second command if the first one succeeds, use double ampersand:
date +%Y && date +%m
Or if you want to run both commands simultaneously, mixing their output unpredictably (probably not what you want, but I thought I'd be thorough), use a single ampersand:
date +%Y & date +%m
echo ´date +%Y´ ´date +m%´
Note the reverse accent (´)
echo `date +%Y` `date +%m`
And to make the minimum change to the OP:
x=$(date +%Y)
x="$x $(date +%m)"
echo "$x"

Test a file date with bash

I am trying to test how old ago a file was created (in seconds) with bash in an if statement. I need creation date, not modification.
Do you have any idea how to do this, without using a command like find with grep?
I'm afraid I cann't answer the question for creation time, but for last modification time you can use the following to get the epoch date, in seconds, since filename was last modified:
date --utc --reference=filename +%s
So you could then so something like:
modsecs=$(date --utc --reference=filename +%s)
nowsecs=$(date +%s)
delta=$(($nowsecs-$modsecs))
echo "File $filename was modified $delta secs ago"
if [ $delta -lt 120 ]; then
# do something
fi
etc..
Update
A more elgant way of doing this (again, modified time only): how do I check in bash whether a file was created more than x time ago?
Here is the best answer I found at the time being, but it's only for the modification time :
expr `date +%s` - `stat -c %Y /home/user/my_file`
If your system has stat:
modsecs=$(stat --format '%Y' filename)
And you can do the math as in Joel's answer.
you can use ls with --full-time
file1="file1"
file2="file2"
declare -a array
i=0
ls -go --full-time "$file1" "$file2" | { while read -r a b c d time f
do
time=${time%.*}
IFS=":"
set -- $time
hr=$1;min=$2;sec=$3
hr=$(( hr * 3600 ))
min=$(( min * 60 ))
totalsecs=$(( hr+min+sec ))
array[$i]=$totalsecs
i=$((i+1))
unset IFS
done
echo $(( ${array[0]}-${array[1]} ))
}

Resources