Хранение старых версий.bak файлов

Я только что научился писать простые сценарии оболочки. Одним из них является то, что я просто дублирую определенные файлы в моей системе, которые имеют решающее значение для меня.

cp /dir/dir/file1 /samedir/samedir/file1.bak

Мои сценарии выполняются каждый раз, когда я подписываюсь в моей системе. Однако это всегда перезаписывает file1.bak, Я хотел бы найти способ сохранить все созданные файлы. Может быть что-то вроде file1(1).bak, file1(2).bak или что-то в этом роде.

VMS отлично подходит для определенных вещей, а именно, что каждый раз, когда кто-то пишет в файл с именем file.bak, он сохранил бы все предыдущие версии, добавив в конец файла ":", указывающий номер версии, то есть: file.bak:1, file.bak:2, file.bak:521, так далее...

Мы использовали, чтобы избавиться от предыдущих версий с помощью команды очисткиpurge file.bak 1-520,

2 ответа

Вы можете использовать некоторое программное обеспечение SCM (также известное как контроль версий), такое как git, mercurial или же fossil,

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

ИМХО самым простым из них был бы ископаемый scm. Это статически соблюдаемый единственный файл, который может обрабатывать такие задания. (Кстати, созданный тем же программистом, который создал SQLite, так что ожидайте качества)

Ваш рабочий процесс может быть таким:

  1. cd в каталог, где нужно отслеживать файлы, и инициализировать репозиторий с помощью команды fossil init (он подготовит один файл базы данных)
  2. Скажите окаменелости, чтобы отслеживать конкретный каталог: fossil open
  3. Добавить файлы / каталоги рекурсивно в хранилище fossil addremove --dotfiles
  4. Сохранить текущий статус каталога в хранилище: fossil commit или если вы заботитесь о целостности файлов, то: fossil commit --sha1sum

Все последующие звонки fossil просто fossil commit (Если вам нужно добавить больше новых файлов или удалить некоторые из отслеживания, просто выполните перед фиксацией fossil addremove --dotfiles)

Таким образом, все изменения в файлах будут храниться во временной шкале и могут быть предварительно просмотрены или сравнены (diff) или извлечены (извлечены) из файла репозитория ether за файлом или полностью восстановят предыдущее состояние всего каталога.

Ты можешь использовать fossil extras --dotfiles выявить новые не отслеживаемые файлы или определить только файлы, которые были изменены fossil changes --abs-paths --sha1sum --header -v

Если вам нужно исключить некоторые файлы или каталог, ископаемые также поддерживают это.

Вы можете видеть временную шкалу изменений в хорошем веб-интерфейсе, созданном одним и тем же файлом, или даже использовать внутреннюю WiKi, чтобы сделать хорошую аннотацию к изменениям.

Если вам нужно удалить некоторый контент из хранилища, fossil обеспечивает механизм, называемый "избегать", чтобы сделать это.

Решение

Если вы не хотите использовать реальную систему управления версиями (как предложено @Alex & @Class Stacker), тогда следующий скрипт bash должен выполнить эту работу:

#!/bin/bash

#############
# Variables #
#############
FILE_LIST="foo.txt bar.doc"  # Space separated list of files to backup (include full path to file)
KEEP_OLD="5"  # How many previous versions to keep

#############
# Functions #
#############
function shift_backups {
        for num in $(seq $KEEP_OLD -1 1) ; do
                old_backup="$file.bak$num"
                if [[ -e $old_backup && $num == $KEEP_OLD ]] ; then
                                echo "    removing oldest file ($old_backup)"
                                rm -f $old_backup
                elif [[ -e $old_backup ]] ; then
                                new_name="$file.bak$(expr $num + 1)"
                                echo "    moving $old_backup to $new_name"
                                mv $old_backup $new_name
                fi
        done
}

################
# Backup Files #
################
for file in $FILE_LIST ; do
        count=1
        while [[ $count -le $KEEP_OLD ]] ; do
                backup_file="$file.bak$count"
                if [[ -e $backup_file ]] ; then
                        echo "$backup_file exists, shifting backups"
                        shift_backups
                        cp $file $backup_file
                        break
                else
                        cp $file $backup_file
                        break
                fi
                count=$(expr $count + 1)
        done
done

объяснение

Чтобы объяснить это, я разобью это и покажу вам логику.

переменные

  • FILE_LIST переменная содержит разделенный пробелами список всех файлов, которые будут включены в резервную копию (убедитесь, что используются полные пути к файлам)
  • KEEP_OLD переменная указывает, когда файлы.bak должны быть удалены. В примере установлено значение 5, означающее, что резервные копии не будут возвращаться дальше, чем 5 версий (при этом самая старая версия - foo.txt.bak5)

Примечание. В зависимости от того, для скольких файлов вы это делаете, возможно, стоит изменить переменную FILE_LIST, чтобы ссылаться на файл и проходить по каждой строке. [Я не проверял эту идею]

функции

Функция shift_backups делает следующее:

  • Перебирает файлы резервных копий от самых старых до самых новых

    for num in $(seq $KEEP_OLD -1 1) ; do
    
  • Если файл резервной копии существует и считается самым старым, он удаляется

    if [[ -e $old_backup && $num == $KEEP_OLD ]]
    
  • Или, если файл резервной копии существует, он будет перемещен в backup number + 1

    elif [[ -e $old_backup ]]
    

Цикл резервного копирования

  • Итерация по каждому файлу в переменной FILE_LIST

     for file in $FILE_LIST ; do
    
  • Продолжайте циклически проверять резервные копии, пока значение переменной count это 1

    while [[ $count -le $KEEP_OLD ]] ; do
    
  • Сохраните имя файла назначения в переменной

    backup_file="$file.bak$count"
    
  • Если файл резервной копии существует, вызывается функция shift_backups, а затем файл копируется (прерывая цикл while, когда это происходит)

    echo "$backup_file exists, shifting backups"
    shift_backups
    cp $file $backup_file
    break
    
  • Если файл резервной копии не существует, он только копируется и цикл while завершается

    else
    cp $file $backup_file
    break
    
  • Увеличивает переменную count

    count=$(expr $count + 1)
    

Выход

В сценарии есть несколько эхо, чтобы помочь понять шаги, которые он предпринял. Например, ниже приведен вывод сценария при запуске в каталоге, где последние версии файлов резервных копий были.bak3:

foo.txt.bak1 exists, shifting backups
    moving foo.txt.bak3 to foo.txt.bak4
    moving foo.txt.bak2 to foo.txt.bak3
    moving foo.txt.bak1 to foo.txt.bak2
bar.doc.bak1 exists, shifting backups
    moving bar.doc.bak3 to bar.doc.bak4
    moving bar.doc.bak2 to bar.doc.bak3
    moving bar.doc.bak1 to bar.doc.bak2

Если вам требуется, чтобы скрипт был тихим, удалите эхо, и он запустится так же.

Другие вопросы по тегам