BASH - Correctly quoting a date command - bash

In the process of writing a bash script to parse a tab-separated file and unfortunately I need the ask the user for a date outside of the contents/creation of the file. I've gotten everything working, except looping through badly entered dates from the user until they enter one matching the desired format.
My debug code-block is as follows...
Code:
#!/bin/bash
USER_INPUT="01-01-2011" # ARBITRARILY ASSIGNING A BAD DATE BECAUSE I'M TOO LAZY TO TYPE ONE IN EACH TIME
EXPERIMENTDATE="$USER_INPUT"
if [[ $OSTYPE == *"linux"* ]]
then
date -d \"$EXPERIMENTDATE\" +%Y-%m-%d > /dev/null 2>&1
else
date -j -f \"%Y-%m-%d\" \"$EXPERIMENTDATE\" +%Y-%m-%d > /dev/null 2>&1
fi
is_valid="$?"
echo -e "$is_valid"
# FYI - $? RETURNS A BINARY FLAG ON THE LAST COMMAND'S EXECUTION. 1 IF ERROR, 0 IF NORMAL EXIT
while [ $is_valid -ne 0 ]; do
echo -e "Invalid date entered. Please enter the day the experiement was conducted on, in exactly the following format. YYYY-MM-DD (e.g. 2011-04-22)"
read USER_INPUT
EXPERIMENTDATE=$USER_INPUT
echo -e "You entered $EXPERIMENTDATE"
if [[ $OSTYPE == *"linux"* ]]
then
echo -e "DEBUG: date -d \"$EXPERIMENTDATE\" +%Y-%m-%d > /dev/null 2>&1"
date -d \"$EXPERIMENTDATE\" +%Y-%m-%d > /dev/null 2>&1
else
echo -e "DEBUG: date -j -f \"%Y-%m-%d\" \"$EXPERIMENTDATE\" +%Y-%m-%d > /dev/null 2>&1"
date -j -f \"%Y-%m-%d\" \"$EXPERIMENTDATE\" +%Y-%m-%d > /dev/null 2>&1
fi
is_valid="$?"
echo -e "DEBUG: $is_valid"
done
echo -e "You entered $EXPERIMENTDATE"
From the above, none of the date commands seem to evaluate correctly within the if's, but executing the debug commands directly on the CLI work.
I'm sure this is going to be a quoting/back-tic deal, but I can't seem to figure it out.

You don't need to escape the quotes that aren't inside similar quotes. For example, not
date -j -f \"%Y-%m-%d\" \"$EXPERIMENTDATE\" +%Y-%m-%d > /dev/null 2>&1
but
date -j -f "%Y-%m-%d" "$EXPERIMENTDATE" +%Y-%m-%d > /dev/null 2>&1

Related

Validate datetime through bash script(i.e. '20200204a')

Validate date format in a shell script
$ date "+%Y%m%d" -d "20200204" > /dev/null 2>&1 ; echo $?
0
$ date "+%Y%m%d" -d "202002/04" > /dev/null 2>&1; echo $?
1
$ date "+%Y%m%d" -d "20200204a" > /dev/null 2>&1 ; echo $?
0
As you can see the invalid input datetime string "20200204a" passed the test.
Question> Is there a way that I can add more strict testing on this input?
Thank you
The +% format controls the output, not input.
Perl to the rescue!
perl -MTime::Piece -e '
$d = shift;
Time::Piece->strptime($d, "%Y%m%d")->strftime("%Y%m%d") eq $d
or exit 1
' "20210229" 2>/dev/null
In Python 3 you can do this :
echo "20200204" | python3 -c '
import sys
import datetime
try:
datetime.datetime.strptime(sys.stdin.read().rstrip(), "%Y%m%d")
except ValueError:
exit(1)'
It will return 1 when there are errors.

Append bash timer to file

I am struggling to both provide a decent timer to a user and append the value in the log. I'm not sure why the following loop isn't logging using exec.
My ideal situation is to add >> log.txt to the echo line, but that breaks the visual timer to the user.
One workaround is to write a redundant echo line after the first:
Some progress was made
exec > >(tee log.txt) 2>&1
SECONDS=0
date1=`date +%s`
while ! [ $((`date +%s` - $date1)) -gt 10 ]; do
echo -ne "$(date -u --date #$((`date +%s` - $date1)) +%H:%M:%S)\r"
#Redundant echo
echo "$(date -u --date #$((`date +%s` - $date1)) +%H:%M:%S)" >> log.txt
done
You could pipe the output to tee -a which will send it to standard output and append to log.txt:
echo "$(date -u --date #$((`date +%s` - $date1)) +%H:%M:%S)" | tee -a log.txt

Redirect standard error to null in Bash - "date: invalid date `Never'"

I require the following error to be redirected to the /dev/null file.
a=$(date -d "Never" +%s) > /dev/null 2>&1
date: invalid date `Never'
The date that is input to the date command is actually being passed through a variable which sometimes acquires "Never". In such a case, an error is shown as shown in the above message which is required to be suppressed.
Is there another method to redirect the output to the null file?
What you are doing currently: redirecting the output of the assignment to /dev/null.
What you want to do: redirecting the error output of the date command to /dev/null
a=$(date -d "Never" +%s 2>/dev/null)
Send only stderr to /dev/null:
a=$(date -d "n" +%s 2>/dev/null)
test :
> a=$(date -d "now" +%s 2>/dev/null); echo $a
1429269352
> a=$(date -d "never" +%s 2>/dev/null); echo $a
>

Implementing a datalogger in bash

Hi I'm a newby in Bash scripting.
I need to log a data stream from a specific IP address and generate a logfile for each day as "file-$date.log" (i.e at 00:00:00 UT close the previous day file and create the correspondig to the new one)
I need to show data stream on screen while it is logged in a file
I try this solution but not works well because never closesthe initial file
apparently the condition check never executes while the first command of the pipe it is something different to an constant string like echo "something".
#!/bin/bash
log_data(){
while IFS= read -r line ; do printf '%s %s\n' "$(date -u '+%j %Y-%m-%d %H:%M:%S')" "$line"; done
}
register_data() {
while : ;
do
> stream.txt
DATE=$(date -u "+%j %Y-%m-%d %H:%M")
HOUR=$(date -u "+%H:%M:%S")
file="file-$DATE.log"
while [[ "${HOUR}" != 00:00:00 ]];
do
tail -f stream.txt | tee "${file}"
sleep 1
HOUR=$(date -u "+%H:%M:%S")
done
> stream.txt
done
}
nc -vn $IP $IP_port | log_data >> stream.txt &
register_data
I'll will be glad if someone can give me some clues to solve this problem.

Formatting a bash cat pipe to mail command

When I wrote this script it works just fine. What it does is it diffs two file
and if the diff fails that indicates that their is no change between the todays file
and the previous days file. That menas the the download is stale.
However when I to email it it is not formatted. I treid putting in a newline
so that the email is legible. But the mail function does not work. The file is
to garbled to read.
#!/bin/bash
dayofweek=$(/bin/date +%w)
today=$(/bin/date +%Y.%m.%d_)
yesterday=$(/bin/date -d '1 day ago' +%Y.%m.%d_)
destination="/sbclocal/stmevt3/dailymetrics/EQ_PERFORMANCE/"
file1=OPTS_TRIP_TRIP_csv_Oct2014.csv
file2=OPTS_TRIPnon-penny1-20_TRIPnon-penny1-20_Oct2014.csv
file3=OPTS_TRIPnon-penny21-50_TRIPnon-penny21-50_Oct2014.csv
file4=OPTS_TRIPnon-penny51-100_TRIPnon-penny51-100_Oct2014.csv
file5=OPTS_TRIPpenny1-20_TRIPpenny1-20_Oct2014.csv
file6=OPTS_TRIPpenny21-50_TRIPpenny21-50_Oct2014.csv
file7=OPTS_TRIPpenny51-100_TRIPpenny51-100_Oct2014.csv
for i in $file1 $file2 $file3 $file4 $file5 $file6 $file7
do
if diff $destination$today$i $destination$yesterday$i > /dev/null ; then
printf "$today$i may be stale - please notify production\n" >> /tmp/eq_diffs.$today
sleep 2
else
echo " " > /dev/null
fi
done
#think we might have to do a if file exists
cat /tmp/eq_diffs.$today | mail -s "EQ performance diffs" casper#casper.com

Resources