Скрипт для удаления старых файлов и оставления самого нового в каталоге в Linux - PullRequest
0 голосов
/ 29 января 2020

У меня есть средство резервного копирования, которое ежедневно выполняет резервное копирование базы данных и сохраняет их в следующем формате:

*_DATE_*.*.sql.gz

с DATE в формате YYYY-MM-DD.

Как я мог удалить старые файлы (сравнив YYYY-MM-DD в именах файлов), соответствующих приведенному выше шаблону, оставив только самый новый.

Пример:

wordpress_2020-01-27_06h25m.Monday.sql.gz
wordpress_2020-01-28_06h25m.Tuesday.sql.gz
wordpress_2020-01-29_06h25m.Wednesday.sql.gz

Если в конце указан только последний файл, значение wordpress_2020-01-29_06h25m.Wednesday.sql.gz должно остаться.

Ответы [ 6 ]

2 голосов
/ 29 января 2020

Предполагается:

  • Предыдущая подстрока, оставленная для части _DATE_, не содержит подчеркивания.
  • Имена файлов не содержат символов новой строки.

Тогда вы бы попробовали следующее:

for f in *.sql.gz; do
    echo "$f"
done | sort -t "_" -k 2 | head -n -1 | xargs rm --

Если ваши head и cut команды поддерживают параметр -z, следующий код будет более устойчивым к специальным символам в именах файлов:

for f in *.sql.gz; do
    [[ $f =~ _([[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2})_ ]] && \
        printf "%s\t%s\0" "${BASH_REMATCH[1]}" "$f"
done | sort -z | head -z -n -1 | cut -z -f 2- | xargs -0 rm --
  • Он использует символ NUL в качестве разделителя строк и допускает любые специальные символы в именах файлов.
  • Сначала он извлекает часть DATE из имени файла, затем предваряет это имя файла в качестве первого поля, разделенного символом табуляции.
  • Затем он сортирует файлы по строке DATE, исключая последний (самый новый), а затем извлекает имя файла, обрезая первое поле, затем удалите эти файлы.
0 голосов
/ 27 апреля 2020

Вы можете использовать мой Python скрипт "rotate-archives" для интеллектуального удаления резервных копий. (https://gitlab.com/k11a/rotate-archives).

Пример запуска удаления архивов:

rotate-archives.py test_mode=off age_from-period-amount_for_last_timeslot=7-5,31-14,365-180-5 archives_dir=/mnt/archives

В результате останутся архивы от 7 до 30 дней с временной интервал между архивами 5 дней, от 31 до 364 дней с временным интервалом между архивами 14 дней, 365 дней с временным интервалом между архивами 180 дней и числом 5.

Но требуется переместить _date_ к началу имени файла или сценария добавить текущую дату для новых файлов.

0 голосов
/ 29 января 2020

Использование двух для l oop

#!/bin/bash
shopt -s nullglob  ##: This might not be needed but just in case
                   ##: If there are no files the glob will not expand
latest=
allfiles=()
unwantedfiles=()

for file in *_????-??-??_*.sql.gz; do
  if [[ $file =~ _([[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2})_ ]]; then
    allfiles+=("$file")
    [[ $file > $latest ]] && latest=$file  ##: The > is magical inside [[
  fi
done

n=${#allfiles[@]}

if ((n <= 1)); then  ##: No files or only one file don't remove it!!
  printf '%s\n' "Found ${n:-0} ${allfiles[@]:-*sql.gz} file, bye!"
  exit 0    ##: Exit gracefully instead
fi

for f in "${allfiles[@]}"; do
  [[ $latest == $f ]] && continue  ##: Skip the latest file in the loop.
  unwantedfiles+=("$f")  ##: Save all files in an array without the latest.
done

printf 'Deleting the following files: %s\n' "${unwantedfiles[*]}"

echo rm -rf "${unwantedfiles[@]}"

В значительной степени зависит от оператора > внутри [[

Вы можете создать новый файл с более низкими датами будь хорошим.

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

Сейчас я на самом деле использую этот скрипт через cron, за исключением части *.sql.gz, так как у меня есть только каталоги для сопоставления, но тот же формат даты, поэтому у меня есть , ????-??-??/ и только ([[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}) в качестве шаблона регулярного выражения.

0 голосов
/ 29 января 2020

Я нашел это в другом вопросе. Хотя он служит цели, но он не обрабатывает файлы на основе их имен файлов.

ls -tp | grep -v '/$' | tail -n +2 | xargs -I {} rm -- {}
0 голосов
/ 29 января 2020

Поскольку шаблон (шар), который вы нам представляете, очень обобщенный c, мы должны сделать здесь допущение.

допущение: шаблон даты - это первая последовательность, которая соответствует регулярному выражению [0-9]{4}-[0-9]{2}-[0-9]{2}

Файлы имеют форму: constant_string_<DATE>_*.sql.gz

a=( *.sql.gz )
unset a[${#a[@]}-1]
rm "${a[@]}"

Файлы имеют форму : *_<DATE>_*.sql.gz

Используя это, это легко сделать следующим образом:

a=( *.sql.gz );
cnt=0; ref="0000-00-00"; for f in "${a[@]}"; do 
   [[ "$f" =~ [0-9]{4}(-[0-9]{2}){2} ]] \
   && [[ "$BASH_REMATCH" > "$ref" ]]    \
   && ref="${BASH_REMATCH}" && refi=$cnt
   ((++cnt))
done
unset a[cnt]
rm "${a[@]}"

[[ expression ]] Доступен дополнительный двоичный оператор =~, имеющий тот же приоритет, что и == и !=. Когда это используется, строка справа от оператора считается расширенным регулярным выражением и соответствует соответствующим образом (как в регулярном выражении (3)). Возвращаемое значение равно 0, если строка соответствует шаблону, и 1 в противном случае. Если регулярное выражение синтаксически неверно, возвращаемое значение условного выражения будет 2. Если включен параметр оболочки nocasematch, сопоставление выполняется без учета букв алфавита c. Любая часть шаблона может быть заключена в кавычки, чтобы ее можно было сопоставить как строку. Подстроки, соответствующие подвыражениям в скобках внутри регулярного выражения, сохраняются в переменной массива BASH_REMATCH. Элемент BASH_REMATCH с индексом 0 является частью строки, соответствующей всему регулярному выражению. Элемент BASH_REMATCH с индексом n является частью строки, соответствующей n-му подвыражению в скобках

source: man bash

0 голосов
/ 29 января 2020

Перейдите в папку, где у вас есть *_DATE_*.*.sql.gz файлы и попробуйте команду ниже

ls -ltr *.sql.gz|awk '{print $9}'|awk '/2020/{print $0}' |xargs rm

или

используйте

`ls -ltr |grep '2019-05-20'|awk '{print $9}'|xargs rm` 

замените /2020/ на шаблон Вы хотите удалить. пример 2020-05-01 заменить на /2020-05-01/

...