Хранение старых версий.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, так что ожидайте качества)
Ваш рабочий процесс может быть таким:
cd
в каталог, где нужно отслеживать файлы, и инициализировать репозиторий с помощью командыfossil init
(он подготовит один файл базы данных)- Скажите окаменелости, чтобы отслеживать конкретный каталог:
fossil open
- Добавить файлы / каталоги рекурсивно в хранилище
fossil addremove --dotfiles
- Сохранить текущий статус каталога в хранилище:
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
это 1while [[ $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
Если вам требуется, чтобы скрипт был тихим, удалите эхо, и он запустится так же.