i have to multiply day by one day minutes
for example today date 2014/08/04
date=4
totalNumberOfminutesPerDay=1440
4*1440
variable=$(date +"%Y.%m.$((%d*1440))");
this gives me this error
-bash: %d*1440: syntax error: operand expected (error token is "%d*1440")
variable=$(date '+%Y.%m.')$(( $(date '+%e') * 1440 ))
Using +%d would fail:
$ (( $(date -d 2014-08-08 '+%d') * 1440 ))
bash: ((: 08: value too great for base (error token is "08")
It is not possible to do the multiplication in date's format string.
You have to do a seperate calculation as fedorqui mentioned in his comment:
variable=$(date +"%Y.%m.$(( $(date +%e)*1440))");
If you want "variable" to be 5760, the following statement is sufficient.
variable=$(( $(date +%e)*1440));
Related
I'm totally new to bash and unix, so the answer to this might be very simple, but despite googling for quite some time I didn't find the solution.
What I'm trying to do is to calculate a difference in days between 2 dates. However, when I convert each date to an epoch second and try to subtract them I get the "Syntax error near unexpected token `/" error.
Here's the script:
# obtain date provided by user in the following format "YYYY-MM-DD"^M
POPULATE_FROM=$2^M
POPULATE_TO=$3^M
#obtain task name^M
TASK=$1^M
FILE_NAME=$(echo $TASK | cut -d'.' -f1)^M
# obtain current date^M
CURRENT_DATE=$(date +%Y-%m-%d)^M
echo "Current $CURRENT_DATE"^M
POPULATE_FROM_DATE=$(date -d "$POPULATE_FROM" +%s)^M
CURRENT_DAY=$(date -d "$CURRENT_DATE" +%s)^M
POPULATE_TO_DATE=$(date -d "$POPULATE_TO" +%s)^M
echo "Current date $CURRENT_DAY"^M
echo "Populate From date $POPULATE_FROM_DATE"^M
echo "Populate to date $POPULATE_TO_DATE"^M
# calculate dates difference in days^M
DIFF_FROM=($POPULATE_FROM_DATE - $CURRENT_DAY) / 86400^M
echo $DIFF_FROM^M
DIFF_TO=($POPULATE_TO_DATE - $CURRENT_DAY) / 86400^M
if ((DIFF_FROM < 0)) ; then^M
# revert it so difference is a positive int^M
DIFF_FROM=$((0-$DIFF_FROM))^M
DIFF_TO=$((0-$DIFF_TO))^M
for ((i=$DIFF_FROM;i>$DIFF_TO;i--));^M
do^M
TASK_DATE="$(date "+%Y-%m-%d" -d "$i days ago")"^M
TEMP_FILE_NAME="$FILE_NAME-$TASK_DATE.json"^M
echo $TEMP_FILE_NAME^M
^M
# copy content of the base task to a new file in order not to overwrite it^M
cp $TASK $TEMP_FILE_NAME^M
^M
TASK_NAME="$FILE_NAME-$TASK_DATE"^M
sed -i "s/$FILE_NAME/$TASK_NAME/" $TEMP_FILE_NAME^M
^M
# replace "T-1" with "T-i"^M
DAY_PATTERN='"IMAS.Loaders.Date" : "T-1"'^M
NEW_DAY_PROPERTY='"IMAS.Loaders.Date" : "'"T-$i"'"'^M
sed -i "s/$DAY_PATTERN/$NEW_DAY_PROPERTY/" $TEMP_FILE_NAME^M
^M
# remove the scheduled cron expression^M
sed -i '/ScheduleExpression/d' $TEMP_FILE_NAME^M
^M
done^M
else^M
echo "Provided date is in the future, no action performed"^M
fi^M
Here's the execution:
bash script.sh "fileName" "2019-08-20" "2019-08-21"
And here's the output I get:
Current 2019-08-22
Current date 1566428400
Populate From date 1566255600
Populate to date 1566342000
")syntax error: invalid arithmetic operator (error token is "line 17: 1566255600
")syntax error: invalid arithmetic operator (error token is "line 19: 1566342000
'script.sh: line 24: syntax error near unexpected token `
'script.sh: line 24: ` for ((i=$DIFF_FROM;i>$DIFF_TO;i--));
Any ideas what am I doing wrong?
As it says, line 17 is wrong.. Its not a valid syntax.
Use this:
DIFF_FROM=$(($(($POPULATE_FROM_DATE - $CURRENT_DAY)) / 86400))
This line define the DIFF_FROM variable which will be used in the other lines below.
I am working on bash. I have to subtract current date from a given date to get number of days as a difference. The given date is in format m/d/yyyy so instead of 09/26/2015 it is 9/26/2015. So even if I try to convert both dates into same format and subtract it says invalid date format.
date1=$(date +"%F")
date2=$(date -d 11/2/2015 +"%F")
diff=$(date "--date=${date2} -${date1}" +%F)
echo $diff days remaining
This is what I had tried with some variations, but doesn't work. What am I doing wrong? Thanks in advance.
Try this:
let diff=(`date +%s -d 11/2/2015` - `date +%s`)/86400
echo $diff days remaining
there are two problems: converting the user-provided date into a normalized form and calculcating the difference in days.
normalizing date
how date interprets a date-string depends on the current locale.
Try to find a locale that uses your special formatting (%m/%d/%Y):
$ LC_TIME=en_US.UTF-8 date -d 1/2/2015
Fri Jan 2 00:00:00 CET 2015
calculating the difference
bash only can only do integer arithmetic, so convert your date first to some integer representation, do the subtraction and convert the representation to days (if needed).
$ LC_TIME=en_US.UTF-8 \
echo $(( ( $(date -d 11/2/2015 +%s) - $(date +%s)) / (3600*24) ))
32
This uses $(...) instead of ... to function substitution.
It also uses $(( ... )) for evalution of math expression instead of the bashism let x=(), so you can use it in POSIX-conformant shell-scripts (e.g. interpreted by /bin/dash)
Here's what isn't working:
> echo $(( ($(date +%s) - $(date +%s -d$(date +%Y-%m-%d))) / 60 ))
date: illegal time format
usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ...
[-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
I've also tried:
> echo $(date +%s -f%Y-%m-%d $(date +%Y-%m-%d))
The following works, but only with a fixed UTC offset that will break during standard time:
> echo $[ ( ( $(date "+%s") - 28800 ) % 86400 ) / 60 ]
Reference: OS X date manual
The number of minutes (or seconds) since midnight can be computed directly from a time alone.
echo $(( $(date "+10#%H * 60 + 10#%M") )) # Minutes since midnight
echo $(( $(date "+(10#%H * 60 + 10#%M) * 60 + 10#%S") )) # Seconds since midnight
Note that this requires only minimal support from date, so will work with either GNU or BSD date.
This works by having date output a string which can be passed directly to the shell's arithmetic expression construct.
Thanks to Petesh for pointing out the need to force numbers with leading zeros to be treated as decimal.
The problem with your first attempt is that you're trying to apply a gnu date option to the BSD date that's on OSX. This has caught me out a lot as I've tried to make scripts compatible between both platforms.
One way is:
seconds_now=$(date +%s)
seconds_midnight=$(date -j -f'%Y-%m-%d %H:%M:%S' "$(date +%Y-%m-%d) 00:00:00" +%s)
minutes_now=$(((seconds_now - seconds_midnight) / 60))
You have to use the full format for the time, otherwise date takes the actual hours, minutes and seconds of the current time, which is not what you want.
Another way is:
Use date +%z to get the offset from UTC, and apply it to the number of minutes past midnight on the day.
offset=$(date +%z) # get TZ offset as [+-]<HH><MM> - for *now*
sign=${offset:0:1} # get sign
hours=${offset:1:2} # get hours
mins=${offset:3:2} # get minutes
minoff=$((10#$hours * 60 + 10#$mins)) # offset in minutes from UTC
from_midnight_utc_mins=$((($(date +%s) % 86400) / 60))
from_midnight_local=$(($from_midnight_utc_mins $sign $minoff))
It's seriously gack, though.
I use 10# for all the numbers in the minoff calculation to prevent the case where two digit numbers with a leading 0 are interpreted as octal, which can yield miscalculations/errors.
I want to have the day of week in the variable DOW.
So I use the following bash-script:
DOM=$(date +%d)
DOW=($($DOM % 7) ) | sed 's/^0*//'
Unfortunately there I get this error: bash: 09: command not found. The expected result is 2 ( 9 % 7 = 2) in the variable $DOW.
How can I get this working?
It works for the days 1-8 but because of the C-hex, there is no number over 8 available and the following message appears: bash: 09: value too great for base (error token is "09").
Use %u. Like this:
DOW=$(date +%u)
From the man page:
%u day of week (1..7); 1 is Monday
You can also use to return the day name
date +'%A'
Using a different %-specifier is the real answer to your question. The way to prevent bash from choking on invalid octal numbers is to tell it that you actually have a base-10 number:
$ DOM=09
$ echo $(( DOM % 7 ))
bash: 09: value too great for base (error token is "09")
$ echo $(( 10#$DOM % 7 ))
2
This works fine here
#!/bin/sh
DOW=$(date +"%a")
echo $DOW
The format option %u returns weekday number [1..7]. Monday is 1.
With date in string:
$ date -d "2022-07-17" +%u
7
Also check return value in $?.
For invalid date, $? is nonzero.
You can use the - flag:
DOM=$(date +%-d)
^
which would prevent the day from being padded with 0.
From man date:
- (hyphen) do not pad the field
Observe the difference:
$ DOM=$(date +%d)
$ echo $((DOM % 7))
bash: 09: value too great for base (error token is "09")
$ DOM=$(date +%-d)
$ echo $((DOM % 7))
2
When running this part of my bash script am getting an error
Script
value=0
for (( t=0; t <= 4; t++ ))
do
d1=${filedates[$t]}
d2=${filedates[$t+1]}
((diff_sec=d2-d1))
SEC=$diff_sec
compare=$((${SEC}/(60*60*24)))
value=$((value+compare))
done
Output
jad.sh: line 28: ((: 10#2014-01-09: value too great for base (error token is "09")
jad.sh: line 30: /(60*60*24): syntax error: operand expected (error token is "/(60*60*24)")
d1 and d2 are dates in that form 2014-01-09 and 2014-01-10
Any solution please?
Prepend the string "10#" to the front of your variables. That forces bash to treat them as decimal, even though the leading zero would normally make them octal.
What are d1 and d2? Are they dates or seconds?
Generally, this error occurs if you are trying to do arithmetic with numbers containing a zero-prefix e.g. 09.
Example:
$ echo $((09+1))
-bash: 09: value too great for base (error token is "09")
In order to perform arithmetic with 0-prefixed numbers you need to tell bash to use base-10 by specifying 10#:
$ echo $((10#09+1))
10
As others have said, the error results from Bash interpreting digit sequences with leading zeros as octal numbers. If you have control over the process creating the date values and you're using date, you can prefix the output format string with a hyphen to remove leading zero padding.
Without prefixing date format with hyphen:
$ (( $(date --date='9:00' +%H) > 10 )) && echo true || echo oops
-bash: ((: 09: value too great for base (error token is "09")
oops
With prefixing date format with hyphen:
$ (( $(date --date='9:00' +%-H) > 10 )) && echo true || echo oops
true
From the date man page:
By default, date pads numeric fields with zeroes. The following
optional flags may follow '%':
- (hyphen) do not pad the field
d1 and d2 are dates in that form 2014-01-09 and 2014-01-10
and then
((diff_sec=d2-d1))
What do you expect to get? ((diffsec=2014-01-09-2014-01-10)) ??
You need to convert the dates to seconds first:
d1=$( date -d "${filedates[$t]}" +%s )
d2=$( date -d "${filedates[$t+1]}" +%s )
(( compare = (d2 - d1) / (60*60*24) ))
(( value += compare ))
Posting some tips here related to the title of this question, but not directly related to the details of the original question. I realize that's a bit controversial action on Stack Overflow, however these related questions:
convert octal to decimal in bash [duplicate]
Value too great for base (error token is "08") [duplicate]
point to this one, and yet they are closed and hence, I could not post this answer there. Therefore, this seemed like a logical place (at least to me) to post this information that may help others in a similar situation, especially new-to-BaSH programmers.
An alternative approach to ensuring a number is treated as a 10-base integer is to use printf. This command instructs printf to treat $num as an integer and round it to 0 decimal places.
num="$(printf "%.0f" "$num")"
Or, if you want to also ensure there are no non-numeric characters in the string, you can do this:
num="$(printf "%.0f" "${num//[!0-9]/}")"
Both commands will strip out leading zeroes and round decimal values to the nearest whole number. Note the first (simpler) solution works with negative numbers, but the second does not (it will always return absolute value).
Note that printf rounds down, meaning .01 to 0.5 is rounded down to 0, while .51 to .99 is rounded up to 1. Basically, the difference between rounding up versus down in this case is that printf rounds down 0.5 and any below. I mention this because 0.5 rounded up is a more common practice.
Now, addressing the OP's specific scenario.... Combining printf with awk allows arithmetic expressions not possible with printf alone.
This
compare=$((${SEC}/(606024)))
could be alternatively be expressed as
compare=$(awk -v sec=$SEC 'BEGIN { print int(sec/(60*60*24))}')
or
compare="$(printf "%.0f" "$(awk "BEGIN { print ( $SEC / ( 60 * 60 * 24 ) ) }")")"
Meanwhile,
value=$((value+compare))
Could be calculated as
value="$(printf "%.0f" "$(awk "BEGIN { print ( $value + $compare ) }")")"
You don't need the $ and the {} in an arithmetic expansion expression. It should look like this:
compare=$((SEC/(60*60*24)))
For 'mm' and 'dd' values in dates, I use this trick:
mm="1${date:5,2}" # where 5 is the offset to mm in the date
let mm=$mm-100 # turn 108 into 8, and 109 into 9