Unix shell script Date format - shell

I'm looking for a Date for like Mar 1 (i.e. space+padded space of day of month)
This is giving correct format => Mar 1
date -d "yesterday 13:00" +"%b %e"
However, when I try to put into a variable, the extra added space is missing.
DATE=`date -d "yesterday 13:00" +"%b %e"`
echo $DATE gives=> Mar 1 (only padded space getting)
Any idea how to get that => Mar 1 (i.e. space+padded space of day of month)

For lots of details, see When to wrap quotes around a shell variable? or I just assigned a variable, but echo $variable shows something else
Basically, you need to quote your variable when you use it:
echo "$DATE"

Related

Want to use a bash for loop to grab descending months

We have a system that would have a cron job that deletes files up to two months ago. I'm trying to write a script to automate this, but I'm fairly new to bash scripting and was wondering if anyone would be able to help. Our files are in %m%Y format and I would be moving them to another directory and then deleting that directory. So for instance since we are in August (082020), I want to move all files up to June (062020) starting this year in Jan (012020).
Here is my script so far, I am basically just trying to print 012020-062020, can anyone let me know if I am on the right track?
#!/bin/bash
MONTHYEAR=$(date +%m%Y)
DELUPTO=$(expr $(date +%m%Y) - 20000)
CURRENTYEAR=$(date +%Y)
for (( i=$DELUPTO; i>=01 + $CURRENTYEAR; $(expr $i - 10000) ))
do
echo "$i"
done
You should loop from the format yyyydd, so start with
for (( i=202006; i>=202001; i-- )); do
echo "${i:4:2}${i:0:4}"
done
It is up to you how you want to achieve this:
yearmonth=$(date +%Y%m)
or
MONTHYEAR=$(date +%m%Y)
yearmonth=${MONTHYEAR:2:4}${MONTHYEAR:0:2}
You know the month and year, extract those values and then turn it into a stamp, but you will need to insert a day value so I would make it say the 1st:
Example of converting timestamps:
# date -d "8/1/2020" +"%s"
1596254400
# date -d #1596254400 +"%b %d %Y %H:%M:%S"
Aug 01 2020 00:00:00
Then create a time stamp of now minutes X days:
date +%s -d "60 days ago"
Once you have common values to compare, Then compare them and if less than 60 days delete Pseudo code:
del_date=$(date +%s -d "60 days ago")
for each file in directory:
#get month and day from file name here, then
file_date=$(date -d "${fmonth}/1/${fyear}" +"%s")
if [[ $file_date -lt $del_date ]] ;then
echo "Older than 60 days by name"
fi
done
Note: It would probably be better to delete files by checking their ages in the system using stat command opposed to reading the details of file name.

Bash date query stopped working

A few months ago I wrote a some bash to get dates. I needed these dates as facts in an ansible script to later use them to get data from the database. This worked fine until today here is the code:
- name: Set date variables
set_fact:
first_day_last_month: "{{lookup('pipe','date -d \"-1 month -$(($(date +%d)-1)) days\" +%Y-%m-%d')}}"
last_day_last_month: "{{lookup('pipe','date -d \"$(date +%Y-%m-01) -1 day\" +%Y-%m-%d')}}"
first_day_current_month: "{{lookup('pipe','date -d \"-$(($(date +%d)-1)) days\" +%Y-%m-%d')}}"
last_day_current_month: "{{lookup('pipe','date -d \"-$(date +%d) days +1 month\" +%Y-%m-%d')}}"
However when I run this now I get an error:
/bin/sh: 1: arithmetic expression: expecting EOF: "08-1"
I tried debugging it on the bash command line:
seven#monstermachine:~$ echo $(date -d "-$($(date +%d)-1)")
08-1: command not found
Mit Nov 8 00:00:00 CET 2017
but until now i'm not getting it fixed.
Anyone have any idea?
%d is zero padded which gives base eight or octal number and 08 is not a valid octal number which thows an error.
What you need is something like :
echo $(date -d "$(($(date +%e)-1))")
Wed Nov 8 07:00:00 IST 2017
Note %e will cause date to be space padded which is equivalent to %_d.
To perform a mathematical expression use $(( expression )) format. I didn't understand the actual logic behind your code, so make sure your code fits the logic.
To get first_day_current_month in your script, you could use:
date +%Y-%m-01
similar for the others, for example to get last_day_last_month:
date -d `date +%Y-%m-01`"-1 day" +%Y-%m-%d
Thanks for the help I will make use of both of your answers to come up with a better working command.

Using quotes within command substitution

I don't understand why this works
dateCMD=$(date -d "4 hours ago")
echo $dateCMD
Tue Oct 18 02:20:34 AEDT 2016
and this works
dateCMD="date"
$dateCMD
Tue Oct 18 06:23:19 AEDT 2016
But not this
dateCMD='date -d "4 hours ago"'
$($dateCMD)
date: extra operand ‘ago"’
How can I get this last case to work?
Short answer: you don't want to do that. Use a function instead.
dateCMD () {
date -d "4 hours ago"
}
dateCMD
Long answer: quotes in the value of a parameter are not "syntactic" quotes; they are just regular data. When you write
dateCMD='date -d "4 hours ago"'
$($dateCMD)
It is evaluated as follows:
$dateCMD expands to date -d "4 hours ago"
The expansion is split into the words date, -d, "4, hours, and ago". The quotes are not treated specially.
The first word, date, is treated as the command with the rest of the words passed as distinct arguments.
date treates "4 as the argument to the -d option. Since date takes only one additional positional argument (the format string), it takes hours as that argument, then complains that ago is an extra operand.
Use BASH array to make it work:
dateCMD=(date -d "4 hours ago")
"${dateCMD[#]}"
Mon Oct 17 11:38:54 EDT 2016
I was typing explanation on your quoting problem but then I noticed very well explained answer from #chepner so avoided adding redundant information in my answer.
To get the last case to work, you can use eval
Of course you should not use eval on any user input without completely validating that input.
dateCMD='date -d "4 hours ago"'
eval $dateCMD

Simultaneous commands

I have a script:
#!/bin/bash
date +%T &
Hours=`date +"%H"` &
Minutes=`date +"%M"` &
Seconds=`date +"%S"`
echo "$Hours:$Minutes:$Seconds"
The objective is to echo date two times and then take out hours, minutes, seconds and calculate how many seconds elapsed between those two commands. So my solution is to write hours, minutes, seconds into variables, then work with those variables.
Problem: echo only echoes seconds which means my interpretation of & is wrong.
How can I fix the & problem? I need those commands to run simultaneously so I can check.
date +%s apparently won't work on certain inputs like:
Wed Mar 4 10:34:59 2015
Wed Mar 4 10:35:08 2015
Will give result of 00:00:01 instead of 00:00:09 or:
Wed Mar 4 10:34:59 2015
Wed Mar 4 17:43:08 2015
will give the result of 12:13:14 instead of 07:08:09. Is it true? Or can I use date +%s and then decrease those two outputs?
You don't need to run the commands simultaneously. Run just one command:
read hours minutes seconds < <( date '+%H %M %S' )
But it can be even simpler: just use the +%s format to get number of seconds since the epoch. You'll get two numbers you can safely subtract.
#!/bin/bash
start=$(date +%s)
sleep 10
end=$(date +%s)
echo The command took $(( end - start )) seconds.
The easiest way is to use the shell variable $SECONDS.
Each time this parameter is referenced, the number of seconds since shell invocation is returned. If a value is assigned to SECONDS, the value returned upon
subsequent references is the number of seconds since the assignment plus the
value assigned. If SECONDS is unset, it loses its special properties, even if
it is subsequently reset.
the main problem is that in this case the command date will be executed tree times to get the values..
so you don't need to execute the commad date too many times
#!/bin/bash
#date +%T &
function myTime(){
now=`date +"%H:%M:%S" &`
}
myTime
s1=`echo $now | cut -d":" -f2`
myTime
s2=`echo $now | cut -d":" -f2`
echo "s1[$s1] - s2[$s2]"
Then you can apply your rules to verify the time elapsed
Regards
Claudio

Using a different date in a shell script

SO, I have a whole script that runs every hour with a date as input. Normally, it takes the current time, but now I need it to run for an interval of time in the past, every hour as well.
What I've done so far is:
DEFINING THE OLD DATE
8 start_date=20131218
9 num_hours=5
10 for i in `seq 1 $num_hours`
11 do
12 date=`date -d "${start_date}+${i} hours"`
13 echo $date # Use this however you want!
14
.
.
.
25 done
The starting date is Dec 18, 2013 and then in each iteration it should give me one more hours from the starting time. This part I found it in another article here and it works. The problem comes when I do
echo $(date)
it prints the current time instead of the time that I previously defined. Of course any other variable that I define from the date has the values from the current time. For instance,
18 datestamp=$(date +%F)
19 hourstamp=$(date +%H)
I'm new in shell programming and I have no idea what to do. Any help?
Thanks in advance.
What you want is this:
18 datestamp=$(date -d "${start_date}+${i} hours" +%F)
19 hourstamp=$(date -d "${start_date}+${i} hours" +%H)
As #BMW said, try to avoid use the date as a variable name to avoid ambiguity.
$(date) will run the command date and export the result.
so when echo it, it will return current date/time.
Second, date is the unix command, avoid to use it as a variable. so this will fix your issue"
DATE=`date -d "${start_date}+${i} hours"`
echo $DATE

Resources