You are not logged in.

#1 2008-12-30 07:50:51

bsdson.tw
Member
From: Taiwan
Registered: 2005-05-06
Posts: 161

A bash script to backup system only with modified files

Hi,

I've made a simple bash script to exam which files are modified and needed to be backed up.
It will use:
1. the hash in Pacman's database (/var/lib/pacman/local/<pkg_ver>/files
2. if no hash in the database, calculate it by our self from cache (/var/cache/pacman/pkg/<pkg_ver>.pkg.tar.gz
3. if no cache found, compare build date and last modified date
4. otherwise, this file better be backed up.

Currently it will only print which files are needed to be backed up, but no backup actually happens. (dry run)
And it is only in early development stage, please be careful.

USAGE:
<the script name> <where to backup files, a directory> <the files, or directories, separated by space, that are going to be examined>...

Here is the code.

#!/bin/bash

# usage:
# $1: file to backup
function do_backup() {
    echo
}

function smart_bak() {
    pkg=$(pacman -Qo "$1" 2>/dev/null)
    if [ 1 -eq $? ] ; then
        # No package owns $1 (locally created)
        if [ "$1" != "${1%.pacsave}" ] ; then
            echo "skip $1 (left by removed package)"
        else
            echo "backup $1 (local file)"
        fi

    else
        pkg=${pkg#$1 is owned by }

        # evaluate
        # by hash
        cur=$(md5sum $1)
        cur=${cur%% *}

        pkg_ver=${pkg/ /-}
        org=$(grep "^${1:1}" "/var/lib/pacman/local/$pkg_ver/files")
        org_hash=${org##*    }
        if [ "$org" != "$org_hash" ] ; then
            # the org hash is in Pacman's database
            if [ "$org_hash" = "$cur" ] ; then
                echo "skip $1 (original config)"
            else
                echo "backup $1 (modified config)"
            fi

        else
            # no hash
            # find out hash myself?
            ARCH=$(uname -m)
            if [ -r "/var/cache/pacman/pkg/$pkg_ver-$ARCH.pkg.tar.gz" ] ; then
                org=$(tar -Oxzf "/var/cache/pacman/pkg/$pkg_ver-$ARCH.pkg.tar.gz" "${1:1}" | md5sum -)
                org_hash=${org%% *}
                if [ "$cur" = "$org_hash" ] ; then
                    echo "skip $1 (original)"
                else
                    echo "backup $1 (modified)"
                fi

            else
                # no cache, may be a AUR package
                # fall back to built date?
                date=$(pacman -Qi ${pkg% *} | grep "^Build Date")
                date=${date#*: }
                date=$(date -d "$date" +%s)
                mod=$(ls -l $1)
                mod=${mod% $1}
                mod=${mod#* * * * * }
                mod=$(date -d "$mod" +%s)
                tmp1=$(expr $mod "+" 60)
                tmp2=$(expr $mod "-" 60)
                if [ "$date" -le "$tmp1" -a "$date" -ge "$tmp2" ] ; then
                    echo "skip $1 (the same date)"
                else
                    echo "backup $1 (unknown)"
                fi
            fi
        fi
    fi
}

function smart_bak_dir() {
    for i in $(ls -A "$1") ; do
        tmp="${1%/}/$i"
        if [ -f "$tmp" ] ; then
            smart_bak "$tmp"
        elif [ -d "$tmp" ] ; then
            smart_bak_dir "$tmp"
        else
            echo "skip $tmp (not a regular file nor a directory)"
        fi
    done
}

#######################################################################

# usage:
# $1: the directory to store this backup
# $2: directory to evalualte for backup

# function main() 
# init
target="$1"
shift

# check
if [ ! -d "$target" -o ! -x "$target" -o ! -w "$target" ] ; then
    exit 4
fi

for i in $* ; do
    if [ -f "$i" ] ; then
        smart_bak "$i"
    elif [ -d "$i" ] ; then
        smart_bak_dir "$i"
    else
        echo "skip $i (unknown argument)"
    fi
done

Good luck,
bsdson

Last edited by bsdson.tw (2008-12-30 07:53:05)

Offline

Board footer

Powered by FluxBB