I have nested for loops going through dates and create a date. How can I check if that specific date is on the weekend or not?
String date is in the format of mm/dd/yyyy but can easily be changed. Each has its own variable $m $d $y
if [[ $(date +%u) -gt 5 ]] ; then
#do something
fi
above code works with current date, not sure how to translate that to accepting a string date.
You could use Ruby Date#cwday in your bash script. For example:
#!/bin/bash
y=2019
m=11
d=10
ruby -rtime -e "puts ([6,7].include? Date.new($y,$m,$d).cwday)"
which outputs true
I like more to use the variable directly:
if [[ $(date -d $your_variable +%u) -gt 5 ]]; then
#do something
fi
Just makes the code cleaner in my opinion.
Related
my bash code basically just needs to generate paths with dates as folder names. But gets stuck at 19820101 for some reason. Really cant quite figure out what's the special case with 1982? Any idea why this is happening?
DTZ=19540101
while [[ $DTZ -le 19850101 ]]
do
echo username#servername:/path/filename_${DTZ}TO0300Z >> afile
DTZ=$(date +%Y%m%d -d "$DTZ+1 months")
done
I can't repro, but try using a more explicit date format.
DTZ=19540101
while [[ $DTZ -le 19850101 ]]
do
echo username#servername:/path/filename_${DTZ}TO0300Z >> afile
DTZ=$(date +%Y%m%d -d "${DTZ:0:4}-${DTZ:4:2}-${DTZ:6:s} + 1 month")
done
The ${string:offset:length} parameter expansion is a Bash-only feature, but so is the [[ conditional you were already using.
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"
I have a date field from a file with 50 dates in mm/dd/yy format. How can I convert it to yymmdd?
I have seen questions similar, but going the opposite direction. I cant seem to apply it the way I need it.
Dates are saved in file as 01/20/72 and I need to convert them to 720120
Currently I have $bDate +%y%m%d as the command, but it is wrong.
Thanks in advance!!
string manipulation: bash regular expressions suffice here:
date="04/13/06"
d='[[:digit:]]'
if [[ $date =~ ($d$d)/($d$d)/($d$d) ]]; then
newdate=${BASH_REMATCH[3]}${BASH_REMATCH[1]}${BASH_REMATCH[2]}
fi
echo $newdate
060413
If you're repeatedly doing this, make it a function:
mdy2ymd() {
local d='[[:digit:]]' newdate
if [[ $1 =~ ($d$d)/($d$d)/($d$d) ]]; then
newdate=${BASH_REMATCH[3]}${BASH_REMATCH[1]}${BASH_REMATCH[2]}
fi
echo $newdate
}
you can use sed and its internal regexp storing vars like
echo "01/20/72" | sed -r 's#(..)/(..)/(..)#\3\1\2#g'
I have some operations to do on files last modified on a specific date. I would like to get the date, stock it in a string, then split it to test if the day corresponds to what I want.
So far, I've been trying things like that:
#!/bin/bash
for i in {45..236}; do
nom=M$i
chem=/Users/nfs/helene/soft/metAMOS-1.5rc3/$nom.fastq/Assemble/out
if [ -e $chem ]; then
IN= $(date -r $chem)
arr=(${IN//\ / })
if [[ ${arr[1]} == 'juin' && ${arr[2]} == '10' ]]; then
echo $nom
#cp $chem/proba.faa /Users/nfs/helene/metagenomes/DB/$nom.faa
fi
fi
done
exit 0
But it seems like the date isn't well stocked in $IN, and I'm not sure about the space-spliting either..
Perhaps the simple mistake is that you didn't place your assignment adjacent to =. It must be:
IN=$(date -r $chem)
And here's a simplified suggestion:
#!/bin/bash
for i in {45..236}; do
nom="M${i}"
chem="/Users/nfs/helene/soft/metAMOS-1.5rc3/${nom}.fastq/Assemble/out"
if [[ -e $chem ]]; then
read month day < <(exec date -r "$chem" '+%b %d')
if [[ $month == 'Jun' && $day == 10 ]]; then
echo "$nom"
# cp "$chem/proba.faa" "/Users/nfs/helene/metagenomes/DB/$nom.faa"
fi
fi
done
exit 0
* See date --help for a list of formats.
* <() is a form of Process Substitution. Check Bash's manual for it.
* Always place your arguments around double quotes when they have variables to avoid word splitting.
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 ;)