I have a directory with a lot of files named in the following date format:
YYYYMMDDHH00
with a com port number on the end. For example
202003240200COM10.txt
202003240300COM10.txt
202003240400COM10.txt
These files are generated every hour by a script and the names are always in the same format.
I want to use the "find" command to return a list of files within a date range that I specify in a script, for example all files between "1 hour ago" and "1 month ago". This script will be run at random times and I always want it to search between that date range relative to the current date, so I don't want any hard coded dates.
I can get the date for 1 hour ago and 3 months ago using the "date" command as so:
bash-4.4$ date --date "1 hour ago" +%Y%m%d%H00
202003241500
bash-4.4$ date --date "1 month ago" +%Y%m%d%H00
202002241600
But I am struggling to get this into the "find" command properly. I have tried the following:
for currentfile in *.txt
do
filedate=${currentfile:0:12}
file_date=$(date +%s -d "${filedate:0:8}${filedate:8:2}${filedate:10:2}${filedate12:2}")
start_date=$(date +%s -d "1 month ago")
end_date=$(date +%s -d "1 hour ago")
if [[ $file_date -ge $start_date && $file_date -le $end_date ]]; then
echo $currentfile
fi
done
But the console output is just a flood of these errors, seemingly one for every file:
date: invalid date 201703190300
date: invalid date 201703190400
date: invalid date 201703190500
date: invalid date 201703190600
date: invalid date 201703190700
date: invalid date 201703190800
date: invalid date 201703190900
date: invalid date 201703191000
date: invalid date 201703191100
date: invalid date 201703191200
date: invalid date 201703191300
date: invalid date 201703191400
date: invalid date 201703191500
date: invalid date 201703191600
date: invalid date 201703191700
date: invalid date 201703191800
date: invalid date 201703191900
Please help :)
date -d
expects a space between the date and time parts. The "CO" is not a valid part of a time stamp, so remove it (there was a typo in your original code which resulted in an unset variable) and delimit hours and minutes by colons:
file_date=$(date +%s -d "${filedate:0:8} ${filedate:8:2}:${filedate:10:2}")
I created test files using
touch 20200{1,2,3,4}2{3,4,5}0200COM{1,2,3}0.txt
Running the following script
#!/bin/bash
start_date=$(date +%s -d "1 month ago")
end_date=$(date +%s -d "1 hour ago")
for currentfile in *.txt ; do
file_date=$(date +%s -d "${currentfile:0:8} ${currentfile:8:2}:${currentfile:10:2}")
if [[ $file_date -ge $start_date && $file_date -le $end_date ]]; then
echo $currentfile
fi
done
only the correct ones were printed:
202002250200COM10.txt
202002250200COM20.txt
202002250200COM30.txt
202003230200COM10.txt
202003230200COM20.txt
202003230200COM30.txt
202003240200COM10.txt
202003240200COM20.txt
202003240200COM30.txt
As correctly noted in the comments by Léa Gris , you can use the YYYYMMDDhhmm format directly and compare the timestamps as strings. This way you don't need to call date
inside the loop at all:
#!/bin/bash
start_date=$(date +%Y%m%d%H%M -d "1 month ago")
end_date=$(date +%Y%m%d%H%M -d "1 hour ago")
for currentfile in *.txt ; do
file_date=${currentfile:0:12}
if [[ ! $file_date < $start_date && ! $file_date > $end_date ]]; then
echo $currentfile
fi
done
Note that the >=
operator doesn't exist, so we have to use negated <
.
As this question already got an answer, I might suggest an alternative approach which doesn't rely on correct file names. Instead, you could just read the meta data of your files and print them accordingly. The first date is the more recent one.
find . -mtime $(date +%s -d "1 hour ago") -mtime $(date +%s -d "1 month ago")
That might be more reliable and would work for other logging applications, as well.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.