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;
Related
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. ;)
Using BASH I want to loop from a start to end date at ten-minute intervals.
I tried
begin_date="2015-01-01 00:00:00"
end_date="2015-02-20 00:00:00"
d=$begin_date
while [ "$d" != "$end_date" ]; do
echo $d
d=$(date -d "${d} + 10 min" +"%Y-%m-%d %H:%M")
done
But it didn't work. Looking at Bash:Looping thru dates
#This works
d=$(date -I -d "${d} + 1 day")
#This doesn't work
d=$(date -d "${d} + 1 day" +"%Y-%m-%d")
What am I missing in the format string?
The expression date -d "${d} + 10 min" seems not to produce a date with an offset of 10 minutes. In fact, when I run your code, I see a date counter going backwards. (Posting this diagnostic as part of your question would help others see where the problem is; you should not require others to run your code just to see what it does.)
Anyway, the sane way to do this is to convert the dates to Unix epoch, then take it from there.
for ((d=$(date -d "$begin_date" +%s); d <= $(date -d "$end_date" +%s); d += 600))
do
date -d #$d +"%F %H:%M"
done
Doing date arithmetic in the shell is probably going to be rather inefficient; converting this to e.g. Awk or Perl might be worth your time if you find it's too sluggish, or need to run it lots of times.
The example you linked to just needs to be adjusted slightly:
#!/bin/bash
## User-specified dates.
# See [GNU Coreutils: Date] for more info
# [GNU Coreutils: Date]: https://www.gnu.org/software/coreutils/manual/html_node/Combined-date-and-time-of-day-items.html#Combined-date-and-time-of-day-items
begin_date="2015-01-01T00:00"
end_date="2015-01-01T00:40"
# Run through `date` to ensure iso-8601 consistency
startdate=$(date --iso-8601='minutes' --date="${begin_date}")
enddate=$(date --iso-8601='minutes' --date="${end_date}")
# Do loop
d="$startdate"
while [ "$d" != "$enddate" ]; do
echo $d
d=$(date --iso-8601='minutes' --date="$d + 10 minutes")
done
Note that the options -I and -d are equivalent to --iso-8601 and --date respectively.
So I'm trying to write a simple script in bash that asks user for input date in
following format (YYYY-dd-mm). Unfortunately I got stuck on first step, which is verifying that input is in correct format. I tried using 'date' with no luck (as it returns actual current date). I'm trying to make this as simple as possible. Thank you for your help!
Using regex:
if [[ $date =~ ^[0-9]{4}-[0-3][0-9]-[0-1][0-9]$ ]]; then
or with bash globs:
if [[ $date == [0-9][0-9][0-9][0-9]-[0-3][0-9]-[0-1][0-9] ]]; then
Please note that this regex will accept a date like 9999-00-19 which is not a correct date. So after you check its possible correctness with this regex you should verify that the numbers are correct.
IFS='-' read -r year day month <<< "$date"
This will put the numbers into $year $day and $month variables.
date -d "$date" +%Y-%m-%d
The latter is the format, the -d allows an input date. If it's wrong it will return an error that can be piped to the bit bucket, if it's correct it will return the date.
The format modifiers can be found in the manpage of date man 1 date. Here an example with an array of 3 dates:
dates=(2012-01-34 2014-01-01 2015-12-24)
for Date in ${dates[#]} ; do
if [ -z "$(date -d $Date 2>/dev/null)" ; then
echo "Date $Date is invalid"
else
echo "Date $Date is valid"
fi
done
Just a note of caution: typing man date into Google while at work can produce some NSFW results ;)
Is there an easier way to calculate yesterday in Bash? This code (used for incremental tars)
mod_time=""
if [ ! -z ${1} ]; then
if [ "${1}" = "i" ]; then
this_month=`date +%m`
this_year=`date +%y`
last_day=`date +%d`
# Subtract one from today's day, to get yesterday.
if [ "${last_day:0:1}" = "0" ]; then
if [ "${last_day:1:1}" > "1" ]; then
last_day=$[$((${last_day:1:1})) - 1]
fi
else
last_day=$[$(($last_day)) - 1]
fi
# zero pad if necessary
if [ 10 -gt $last_day ]; then
last_day="0$last_day"
fi
mod_time=" --newer-mtime $this_month/$last_day/$this_year "
fi
fi
has a couple of problems like calculating day 0, and also not doing the right thing at the end of the month. I don't want to build in leap year calculations, and am wondering if there's an easy way to do this in Bash. If not, I'll use Clojure or Python.
Perhaps I'm missing your point, but why not:
$ date -d yesterday
Wed Feb 1 11:53:12 EST 2012
(might be a GNU extension so no promises you'll have it). If you do, I'd say it's easier :).
This might help
date -d "yesterday" +%Y%m%d
return
20120202
date -d yesterday
Well for me this seems a bit shorter:
date --date "1 day ago"
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]} ))
}