Mantendo versões antigas de arquivos .bak

1

Acabei de aprender a escrever scripts de shell simples. Um deles é que basta duplicar certos arquivos no meu sistema que são cruciais para mim.

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

Meus scripts são executados toda vez que eu faço login no meu sistema. No entanto, sempre sobrescreve file1.bak . Eu gostaria de encontrar uma maneira de manter todos os arquivos criados. Talvez algo como file1(1).bak , file1(2).bak ou algo parecido.

O VMS foi ótimo para certas coisas, ou seja, toda vez que alguém gravaria em um arquivo chamado file.bak , ele manteria todas as versões anteriores adicionando um ':' no final do arquivo indicando o número da versão ou seja: file.bak:1 , file.bak:2 , file.bak:521 , etc ...

Costumávamos nos livrar das versões anteriores com o comando purge purge file.bak 1-520 .

    
por user63274 08.01.2017 / 08:04

2 respostas

2

Você pode usar o software SCM (também conhecido como controle de versão), como git , mercurial ou fossil .

Desta forma, você evitará uma enorme quantidade de bak arquivos no diretório de trabalho e manterá o controle de todas as versões anteriores ao mesmo tempo.

IMHO mais simples seria fossil-scm É estaticamente cumprido um único arquivo que pode lidar com tais trabalhos. (Aliás criado pelo mesmo programador que criou o SQLite, então espere qualidade)

Seu fluxo de trabalho pode ser assim:

  1. cd para o diretório onde os arquivos precisam ser rastreados e o repositório init com o comando fossil init (irá preparar um único arquivo de banco de dados)
  2. Diga ao fóssil para rastrear um diretório específico: fossil open
  3. Adicione arquivos / diretórios de forma recursiva ao repositório fossil addremove --dotfiles
  4. Salvar o status atual do diretório para o repositório: fossil commit ou se você se importa com a integridade dos arquivos, em seguida: fossil commit --sha1sum

Todas as chamadas subseqüentes de fossil são apenas fossil commit (se você precisar adicionar mais arquivos novos ou remover alguns do acompanhamento, basta emiti-los antes de confirmar fossil addremove --dotfiles )

Dessa forma, todas as alterações nos arquivos serão mantidas na linha do tempo e poderão ser visualizadas ou comparadas (diff) ou extraídas (checkout), do repository ether arquivo por arquivo ou restaurar completamente o estado anterior de todo o diretório.

Você pode usar fossil extras --dotfiles para revelar novos arquivos não rastreados ou localizar apenas arquivos que foram alterados fossil changes --abs-paths --sha1sum --header -v

Se você precisar excluir alguns arquivos ou diretórios, o suporte fóssil também.

Você pode ver a linha do tempo das alterações em uma interface da web agradável produzida pelo mesmo arquivo único ou até mesmo usar o WiKi interno para fazer uma boa anotação nas alterações.

Se você precisar remover algum conteúdo do repositório, fossil fornecerá um mecanismo chamado "shunning" para fazer isso.

    
por 08.01.2017 / 08:48
0

Solução

Se você não deseja usar um sistema de controle de versão real (como sugerido pelo @Alex & @Class Stacker), o seguinte script bash deve fazer o trabalho:

#!/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

Explicação

Para explicar isso, vou dividi-lo e mostrar a você a lógica.

Variáveis

  • A variável FILE_LIST contém uma lista separada por espaços de todos os arquivos a serem incluídos no backup (assegure-se de que os caminhos de arquivo completos sejam usados)
  • A variável KEEP_OLD indica quando os arquivos .bak devem ser excluídos. No exemplo, ele é definido como 5, o que significa que seus backups não retornarão mais de 5 versões (com foo.txt.bak5 sendo a versão mais antiga)

Nota: Dependendo do número de arquivos para os quais você está fazendo isso, talvez valha a pena ajustar a variável FILE_LIST para fazer referência a um arquivo e percorrer todas as linhas de lá. [Eu não testei essa ideia]

Funções

A função shift_backups faz o seguinte:

  • Faz um loop pelos arquivos de backup do mais antigo para o mais novo

    for num in $(seq $KEEP_OLD -1 1) ; do
    
  • Se o arquivo de backup existir e for a contagem mais antiga, ele será excluído

    if [[ -e $old_backup && $num == $KEEP_OLD ]]
    
  • Ou se o arquivo de backup existir apenas, ele será deslocado para backup number + 1

    elif [[ -e $old_backup ]]
    

Backup Loop

  • Iterar cada arquivo na variável FILE_LIST

     for file in $FILE_LIST ; do
    
  • Continue a percorrer as verificações de backup enquanto o valor da variável count for 1

    while [[ $count -le $KEEP_OLD ]] ; do
    
  • Armazene o nome do nome do arquivo de destino em uma variável

    backup_file="$file.bak$count"
    
  • Se o arquivo de backup existir, a função shift_backups é chamada e, em seguida, o arquivo é copiado (quebrando o loop while quando isso acontece)

    echo "$backup_file exists, shifting backups"
    shift_backups
    cp $file $backup_file
    break
    
  • Se o arquivo de backup não existir, ele será copiado & o loop while é encerrado

    else
    cp $file $backup_file
    break
    
  • Incrementa a variável count

    count=$(expr $count + 1)
    

Saída

O script tem alguns ecos para ajudar a entender os passos que ele deu. Por exemplo, abaixo está a saída do script quando executado em um diretório em que as versões mais recentes dos arquivos de backup eram .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

Se você precisar que o script seja silencioso, remova os ecos e ele será executado da mesma forma.

    
por 09.01.2017 / 13:22