Скрипт Bash: условное удаление старых файлов с сохранением последних копий

Скрипт Bash: условное удаление старых файлов с сохранением последних копий

Примечание: Хотя есть ответ от jeff-schaller, он зависит от zsh; поэтому я хотел бы получить ответ, основанный на Bash.

Мне нравится создавать скрипт Bash для условного удаления старых файлов из резервной копии.

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

1. Сохраните последнюю копию Edge_Profile_*.tgzи удалите остальную часть.Edge_Profile_*.tgz только если они старше 5 дней.

2. Сохраните последнюю копию Firefox_Profile_*.tgzи удалите остальную часть.Firefox_Profile_*.tgz .неважно, сколько им лет.

Вот как я изменил этот ответ AskUbuntu:https://askubuntu.com/a/933098/928088

Сценарий:

#!/bin/bash

LOG_FILE="/home/admn/Cleanup.log"
TEMP_LOG="/tmp/Temp_Cleanup.log"

mv $LOG_FILE $TEMP_LOG

{

cd /home/admn/Downloads/Test;

echo "Cleanup log:" `date`

find /home/admn/Downloads/Test/Edge_Profile_*.tgz -type f \( -mtime +5 -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
    sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
        case "$flag" in 
            'Y') echo rm "$file" 
               ;; 
            *) echo "skipping $file (too new)"
               ;; 
        esac;
done

echo

find /home/admn/Downloads/Test/Firefox_Profile_*.tgz -type f \( -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
    sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
        case "$flag" in 
            'Y') echo rm "$file" 
               ;; 
            *) echo "skipping $file (too new)"
               ;; 
        esac        
done

} &>> $LOG_FILE

cat $TEMP_LOG >>$LOG_FILE

exit;

Вывод в файле журнала echo:

/usr/local/scripts/cleanup.sh

rm /home/admn/Downloads/Test/Edge_Profile_Jul_06_2021_00-35.tgz
rm /home/admn/Downloads/Test/Edge_Profile_Jul_07_2021_00-35.tgz
....
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new)
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new)
....

rm /home/admn/Downloads/Test/Firefox_Profile_Jul_01_2021_00-35.tgz
rm /home/admn/Downloads/Test/Firefox_Profile_Jul_02_2021_00-35.tgz
....

Вывод в файле журнала во время фактического выполнения скрипта, без echo:

/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new): No such file or directory
/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new): No such file or directory
....

Всего файлов в каталоге: 20 файлов

1, Edge_Profile_*.tgz: С 06 июля по 17 июля: 12 файлов

2, Firefox_Profile_*.tgz: С 01 июля по 08 июля: 8 файлов

Проблемы:

(1) ЯдуматьСкрипт в целом работает, но я не уверен, так как большую его часть я изменил, не зная, что происходит.

(2) Вывод в файл журнала:

Я бы предпочел точно такой же вывод в файле журнала, который я получаю с помощью echo, за исключением только имен файлов (не с полным путем), например:

rm Edge_Profile_Jul_11_2021_00-35.tgz

skipping Edge_Profile_Jul_12_2021_00-35.tgz (too new)

ОС: Ubuntu MATE 21.04

Большое спасибо.

решение1

Манипулировать файлами на основе времени их модификации гораздо проще в оболочке, которая позволяет вам получать к ним прямой доступ. zsh — одна из таких оболочек. Просто sudo apt install zshустановить ее. Поскольку ваши файлы, по-видимому, находятся в одном каталоге, этот ответ нерекурсивный. Сначала продемонстрируем более простой случай:

  • Чтобы сохранить последнюю копию Firefox_Profile_*.tgz и удалить все остальные, независимо от их возраста:

    echo would rm -v -- Firefox_Profile_*.tgz(.om[2,-1])
    

    Удалитьecho would часть, если она выглядит правильно. Это используетквалификатор glob (wildcard)внутри скобок нужно сделать три вещи:

    • выберите только простые файлы (не каталоги, не сокеты и т.п.) с помощью.
    • упорядочить (сортировать) файлы по времени их изменения, от новых к старым, сom
    • выберите фрагмент результирующего списка, начиная со второго элемента и до конца, пропуская первый (самый новый) файл, с[2,-1]

    Если соответствующих файлов нет, zsh остановится и выдаст сообщение «zsh: совпадений не найдено» и не выполнит файл rm.

  • Чтобы сохранить последнюю копию Edge_Profile_*.tgz и удалить остальные, только если они старше 5 дней, сначала мы берем последнюю:

    newest=(Edge_Profile_*.tgz(.om[1]))
    

    ... а затем мы получаем те, которые старше пяти дней:

    older=(Edge_Profile_*.tgz(.m+5))
    

    Новая часть здесь — это модификатор +5on m. Он выбирает файлы старше 5 дней. После этого мы убеждаемся, что самый новый не находится в списке для удаления:

    remove=("${(@)older:|newest}")
    

    Новая часть здесь — это символ вычитания массива.:| ; он задокументирован вРаздел «Расширение параметров» руководства zsh. Он выбирает элементы "older", которых нет в "newest". Наконец, мы удаляем этот список файлов:

    echo would rm -v -- "${remove[@]}"
    

Связанный контент