#! /bin/bash # backup a file (ver seq.) #H bkup [-hpiv][-n N] files... #H bkup は指定されたファイルに通番を付加してコピーします。 #H たとえば filea は filea.1 としてコピーします。 #H 既に filea.N が存在するなら filea.(N+1) としてコピーを作成します。 #H また、filea.1, filea.2 .... filea.N をまとめて削除することも出来ま #H す。(purge) #H #H -h このメッセージを表示します。 #H -n 続く整数を上限とした世代管理を行います。 #H 世代上限が N の時、backup が N を越えるようであれば、最も古い #H ファイルを削除し、各バックアップファイルの通番を1つづつずらし #H ます。 #H -p 指定されたファイルのコピー(filea.N) をまとめて削除します。 #H -i 各引き数を処理するたびに実行の確認をします。 #H 応答方法は4種類あり、(y)-現在の処理続行, (n)-現在の処理中止, #H (a)-以降の全処理について(y) を適用, (q)-bkup の中止 #H -v 処理状況を表示します。 function getseq { ls $f.[0-9]* 2>/dev/null | gawk -F. 'BEGIN{max=0}{if ($NF>max) max=$NF}END{print max}' } function backup { org=$1 bkup=$2 if [ ${vsw}X = X ] ;then cp $org $bkup else /bin/echo -e "backup $org to $bkup \c" cp $org $bkup [ $? -eq 0 ] && echo "...done" fi } function purge { org=$1 shift bkups="$*" [ -f $org ] || { ver=`getseq $org` cp ${org}.$ver $org } if [ ${vsw}X = X ] ;then rm $bkups else /bin/echo -e "purge $org [$bkups]\c" rm $bkups [ $? -eq 0 ] && echo "...done" fi } function file_shift { file=$1 let max=$2-1 allseq=/tmp/bkup_seqA.$$ saves=/tmp/bkup_seqB.$$ purges=/tmp/bkup_seqC.$$ trap "/bin/rm -f $allseq $saves $purges" HUP EXIT INT ls -rt ${file}.[0-9]* > $allseq 2>/dev/null if [ $max -gt 0 ] ; then tail -$max $allseq > $saves else touch $saves fi comm -23 $allseq $saves > $purges num_olds=`cat $purges|wc -l` if [ x$vsw = xv -a $num_olds -gt 0 ]; then /bin/echo -e "purge files [ \c" cat $purges | while read x do /bin/echo -e "$x \c" done echo " ]" fi # remove older file if [ x$isq = xi ]; then RM="rm -i" else RM="rm -f" fi $RM `cat $purges` rm -f $allseq $saves $purges } export isw="" export vsw="" export cmd=backup export max=0 while getopts :vhpin: n do case $n in i) isw="i" ;; v) vsw="v" ;; n) max=$OPTARG ;; p) cmd="purge" ;; h) sed -e '/^#H/s/^..//p' -e d $0 | more exit 0; ;; ?) echo " unkown option, try -h" ;; esac done let argc=$OPTIND-1 shift $argc for f in $* do case $cmd in backup) ver=`getseq $f` if (($ver>=$max)); then file_shift $f $max fi let ver=ver+1 new=$f.$ver ;; purge) new="`echo ${f}.[0-9]*`" if [ "$new" = ${f}'.[0-9]*' ] ;then echo "$f has no backups" exit; fi ;; esac if [ ${isw}X = X ] ; then $cmd $f $new else read -p "$cmd $f $new ?(y/n/a/q) " ans case $ans in y|Y) $cmd $f $new ;; n|N) ;; a|A) isw="" ;; q|Q) exit;; esac fi done