Работая исходя из того, что вы имеете в виду 90 дней - если вам нужны именно месяцы, мы тоже можем это проверить, но это другая логика.
вот код, с которым вы могли бы работать -
(вы сказали, что не хотите работать из списка, поэтому я отредактировал для использования текущего каталога.)
$: cat chkDates
# while read f # replaced with -
for f in *[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*
do # first get the epoch timestamp of the file based on the sate string embedded in the name
filedate=$(
date +%s -d $(
echo $f | sed -E 's/.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*/\1/'
) # this returns the date substring
) # this converts it to an epoch integer of seconds since 1/1/70
# now see if it's > 90 days ( you said 3 months. if you need *months* we have to do some more...)
daysOld=$(( ( $(date +%s) - $filedate ) / 86400 )) # this should give you an integer result, btw
if (( 90 < $daysOld ))
then echo $f is old
else echo $f is not
fi
done # < listOfFileNames # not reading list now
Вы можете передать date
дату для отчета,и формат для его представления.
объяснение шаблона sed
Обратите внимание на команду sed -E 's/.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*/\1/'
.Это предполагает, что формат даты будет последовательно YYYY-MM-DD
, и не проверяет разумность.Он с радостью примет любые 4 цифры, затем 2, затем 2, разделенные тире.
-E
использует расширенные регулярные выражения, поэтому парены ()
могут обозначать значения, которые нужно запомнить, без необходимости \
.,.
означает любой символ, а *
означает любое число (включая ноль) предыдущего шаблона, поэтому .*
означает ноль или более символов, съедая всю строку до даты.[0-9]
означает любую цифру.{x,y}
устанавливает минимальное (x) и максимальное (y) количество последовательных совпадений - только с одним значением {4}
означает, что подойдет только 4 из предыдущего шаблона.Итак, '.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*'
означает игнорирование как можно большего количества символов, пока не увидите 4 цифры, затем тире, 2 цифры, затем тире, затем 2 цифры;запомните этот шаблон (()
), затем игнорируйте все символы позади него.
В подстановке \1
означает первое запомненное совпадение, поэтому
sed -E 's/.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*/\1/'
означает поиски запомните шаблон даты в именах файлов и замените полное имя только этой частью в выходных данных.Предполагается, что дата будет присутствовать - в имени файла, в котором нет даты, шаблон не будет совпадать, и будет возвращено все имя файла, поэтому будьте осторожны с этим.
(надеюсь, это помогло.)
Изолируя строку даты из имен файлов с помощью sed
(ваши примеры были согласованы по формату, поэтому я использовал это), мы передаем ее и запрашиваем метку времени эпохи UNIX этой даты.Строка с использованием date +%s -d $(...)
, чтобы представить файл с математическим номером.
Вычтите, что из текущей даты в том же формате вы получите приблизительный возраст файла в секундах.Разделите , что , на количество секунд в дне, и вы получите дни.Дата файла по умолчанию будет равняться полуночи, но математика будет отбрасывать дроби, поэтому она разбирается.
вот список файлов, который я сделал, исходя из ваших примеров
$: cat listOfFileNames
fileone.log.2018-03-23
fileone.log.2018-09-23
file_two_2018-03-23.log
file_two_2018-08-23.log
filethree.log.2018-03-23
filethree.log.2018-10-02
file_four_file_four_2018-03-23.log
file_four_file_four_2019-03-23.log
Я добавил файл для каждого из них, который будет в течение 90 дней с момента публикации, включая файл с «датой», который может легко случиться с подобными вещами.
Вотвывод.
$: ./chkDates
fileone.log.2018-03-23 is old
fileone.log.2018-09-23 is not
file_two_2018-03-23.log is old
file_two_2018-08-23.log is not
filethree.log.2018-03-23 is old
filethree.log.2018-10-02 is not
file_four_file_four_2018-03-23.log is old
file_four_file_four_2019-03-23.log is not
Это то, что вы имели в виду?
Альтернативный способ чистого bash, чтобы получить только строку даты
(Вам все еще нужно date
, чтобы преобразовать в секунды эпохи ...)
вместо
filedate=$(
date +%s -d $(
echo $f | sed -E 's/.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*/\1/'
) # this returns the date substring
) # this converts it to an epoch integer of seconds since 1/1/70
, который, кажется, не работает для вас, попробуйте это:
tmp=${f%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*} # unwanted prefix
d=${f#$tmp} # prefix removed
tmp=${f#*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]} # unwanted suffix
filedate=${d%$tmp} # suffix removed
filedate=$( date +%s --date=$filedate ) # epoch time
Это трудно читать, но не нужно создавать столько подпроцессов, чтобы выполнить работу.:)
Если это не сработает, то я с подозрением отношусь к вашей версии date
.Шахта:
$: date --version
date (GNU coreutils) 8.26