Идентификация файлов старше x-месяцев только по имени файла и удаление их - PullRequest
0 голосов
/ 24 октября 2018

У меня есть 4 разных файла с разными форматами fileName.date, в которых часть имени встроена в дату.Я хочу идентифицировать файлы старше 3 месяцев на основе их имени только потому, что файлы также будут редактироваться / изменяться позже.Я хочу создать скрипт оболочки и запустить его как cron.Ниже приведен файл в том же каталоге:

  1. fileone.log.2018-03-23 ​​
  2. file_two_2018-03-23.log
  3. filethree.log.2018-03-23 ​​
  4. file_four_file_four_2018-03-23.log

Я проверил существующий пример, но не нашел того, что на самом деле ищу!

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Работая исходя из того, что вы имеете в виду 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
0 голосов
/ 24 октября 2018

ОБНОВЛЕНИЕ:

Простая версия:

Метод использования даты внутри имени файла:

typeset stamp=$(date --date="90 day ago" +%s)
for file in /directory/*.log; do
        fdate="$(echo "$file" | sed 's/[^0-9-]*//g')"
        fstamp=$(date -d "${fdate} 00:00:00"  +"%s")
        if [ ${fstamp} -le ${stamp} ] ; then
                echo "${file} : ${fdate} (${fstamp})"   
        fi
done

AБолее полная версия :

Эта версия будет просматривать все файлы, если не удается получить значение даты из файла, в который она перемещается.

typeset stamp=$(date --date="90 day ago" +%s)
for file in /tmp/* ; do
        fdate="$(echo "$file" | sed 's/[^0-9-]*//g')"
        fstamp=$(date -d "${fdate} 00:00:00"  +"%s" 2> /dev/null)
        [[ $? -ne 0 ]] && continue
        if [ ${fstamp} -le ${stamp} ] ; then
                echo "${file} : ${fdate} (${fstamp})"   
        fi
done

вывод:

/tmp/file_2016-05-23.log : 2016-05-23 (1463976000)
/tmp/file_2017-05-23.log : 2017-05-23 (1495512000)
/tmp/file_2018-05-23.log : 2018-05-23 (1527048000)
/tmp/file_2018-06-23.log : 2018-06-23 (1529726400)
/tmp/file_2018-07-23.log : 2018-07-23 (1532318400)

в этом примере игнорировалось следующее:

/tmp/file_2018-08-23.log : 2018-08-23 (1534996800)
/tmp/file_2018-10-18.log : 2018-10-18 (1539835200)
...