date: invalid date ‘19820101+1 months’ - bash

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.

Related

check if String Date (mm/dd/yyyy) is weekend - bash

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.

Problems with "while" bash

I need to control files in a folder... The script has to wait the file until it exists...
These files have the name... The format is file_d01_YYYY-MM-DD_HH:00:00. For example:
file_d01_2018-11-12_00:00:00
file_d01_2018-11-12_01:00:00
And so on, for 7 days ahead.
!/bin/bash
ZZ=`date +%k`
date=$(date +%Y%m%d)
if [[ $ZZ -ge 2 ]] && [[ $ZZ -lt 14 ]] ; then #03:45 UTC
ZZ=00
PARAM=`date +%Y%m%d`$ZZ
PARAM2=`date +%Y-%m-%d`
elif [[ $ZZ -ge 14 ]] && [[ $ZZ -lt 23 ]] ; then #15:45 UTC
ZZ=12
PARAM=`date +%Y%m%d`$ZZ
PARAM2=`date +%Y-%m-%d`
fi
rundir=/home/$PARAM/wrfv3
dir=/home/$PARAM
data=$(date +%Y-%m-%d)
data1=$(date -d "1 day" +%Y-%m-%d)
data2=$(date -d "2 day" +%Y-%m-%d)
data3=$(date -d "3 day" +%Y-%m-%d)
data4=$(date -d "4 day" +%Y-%m-%d)
data5=$(date -d "5 day" +%Y-%m-%d)
data6=$(date -d "6 day" +%Y-%m-%d)
days=( "$data" "$data1" "$data2" "$data3" "$data4" "$data5" "$data6" ) #array of days
values=( {00..23} ) #array of 24 hours
echo ${#values[#]}
# Here, using to loops, I check if files exist...for every day and hour
for day in "${days[#]}"; do
for value in "${values[#]}"; do
echo file_d01_${day}_${value}:00:00
while [ ! -f $rundir/file_d01_2018-11-15_20:00:00 ] # while file doesn't exist...wait...and repeat checking till it exists...
do
echo "waiting for the file"
sleep 10
done
echo "file exists"
sleep 5
done
done
I receive always "waiting for the file"...and they exist... where is the problema in the code?
You should add the double quotes "" to protect the path. It's a good practice. Also bash expansion escapes the : character, so maybe it is an issue in your context (not in the one i did the test).
while [ ! -e "$rundir/file_d01_2018-11-15_20:00:00" ]
I would suggest to follow those steps:
Protect the path with double quotes "" (not simple ones, otherwise $rundir won't be expanded)
Write echo "waiting for the file $rundir/file_d01_2018-11-15_20:00:00" to see what path you're testing
Additionally, use -e to see any changes (-e checks for a path existence, not only a regular file one)
Note: the brackets [ ] invokes in fact test. So, man test will give you the operators you can use and their meanings. Also nowadays bash has double brackets [[ ]] as built-in operators, more powerful, which can be used instead.
The code in the question contains:
echo file_d01_${day}_${value}:00:00
while [ ! -f $rundir/file_d01_2018-11-15_20:00:00 ]
It's calculating a file name, echoing it, and then checking for a (probably different) fixed, unchanging, file name. It should check for the calculated file name. For example:
file=file_d01_${day}_${value}:00:00
echo "$file"
while [ ! -f "$rundir/$file" ]
To make debugging easier, it would be better to have:
filepath=$rundir/file_d01_${day}_${value}:00:00
echo "$filepath"
while [ ! -f "$filepath" ]
The full code in the question has many issues (starting with a broken shebang line). It's a good idea to make Bash code Shellcheck-clean.

Stock date in a string then split it for tests

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.

Get the substring from a filename and compare to Hour (HH) of current date/timestamp using Shell Script

Say I have a filename ABC.20131212.XX.xml where XX is HH (hour). I need to get the value of XX and compare it to the current hour of the system time. If it's equal, then, i'll rename that file. So if it's 12pm (12:00), I should get the file with ABC.20131212.12.xml and rename it. How can I achieve the comparison in shell script?
Here's how to get started in pure bash without starting external commands:
a=ABC.20131212.XX.xml
# Strip off .xml
b=${a%.xml}
# Extract last 2 characters
xx=${b: -2}
and the hour can be got with
time=`date +'%H'`
Comparison and rename can be done like this
if [[ $time -eq $xx ]]
then
mv something somewhere
fi
Here's how you can do it using Bash built-in regex matching:
file=foobar.11.xml
if [[ $file =~ .*([0-9][0-9])\.xml ]]; then
if [[ "${BASH_REMATCH[1]}" -eq $(date "+%I") ]]; then
# $file has current hour in its name
fi
fi
Use the +%H option with date for comparing to a 24-hour time system.
Here is the Script you can use(Change path accordingly):
`
!/bin/bash
Path=/Your/Path/Here/*
for l in $Path
do
a=$l
b=${a%.xml}
xx=${b: -2}
time=date +"%I"
if [[ $time -eq $xx ]]
then
mv $l /New/file/name/path/newfile.txt
fi
done
exit 0`

How to grave the Date from this command in bash script

!/bin/bash
# When a match is not found, just present nothing.
shopt -s nullglob
# Match all .wav files containing the date format.
files=(*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]*.wav)
if [[ ${#files[#]} -eq 0 ]]; then
echo "No match found."
fi
for file in "${files[#]}"; do
# We get the date part by part
file_date=''
# Sleep it to parts.
IFS="-." read -ra parts <<< "$file"
for t in "${parts[#]}"; do
# Break from the loop if a match is found
if [[ $t == [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
file_date=$t
break
fi
done
# If a value was not assigned, then show an error message and continue to the next file.
# Just making sure there is nothing in Array and date before it moves on
if [[ -z $file_date ]]; then
continue
fi
file_year=${file_date:0:4}
file_month=${file_date:4:2}
mkdir -p "$file_year/$file_month"
# -- is just there to not interpret filenames starting with - as options.
echo "Moving: ./"$file "to: " "./"$file_year"/"$file_month
mv "$file" "$file_year/$file_month"
done
Now there are files I would need to do the date to gra the date and then move it like I do now. for example there is a file called meetme.. its a wav file and I have DIR with YYYY/MM and would like to move thoses files without YYYYMMDD in file name already
If you're writing a program to do something with that information, then you might prefer seconds-since-epoch and use date to get the date in the desired format.
$ date -d #$(stat --format='%Y' testdisk.log) +%Y%m%d
20130422
You can also get the ascii representation, and then manipulate the string.
$ stat --format='%y' testdisk.log
2013-04-22 09:11:39.000000000 -0500
$ date_st=$(stat --format='%y' testdisk.log)
$ date_st=${date_st/ */}
$ date_st=${date_st//-/}
$ echo ${date_st}
20130422

Resources