比这篇新的文章: 生成华容道所有可求解的开局含镜像263977种,不含镜像132156种
比这篇旧的文章: batch scp

Vbak - Linux 下备份小工具

语言: Bash, 标签: linux bash vbak 2008/10/28发布 1年前更新 更新记录
作者: vvoody, 点击963次, 评论(2), 收藏者(0), , 打分:

背景
主题: 字体:
001 #!/bin/bash
002 #
003 # Copyright (C) 2008-3001, vvoody <wxj.g.sh{AT}gmail.com>
004 # Released under GNU GPL v3.
005 #
006 # vbak first finished without test strongly at 2008-10-20 night
007 # vbak can be for daily use, I think, at 2008-10-27 night
008 #
009 # Get the latest version:
010 # svn checkout http://vvoodys.googlecode.com/svn/trunk/vbak vbak
011 #
012 # TODO:
013 #     remove the temp files periodically;
014 #     find a easy to remove one line from file;
015
016
017 # die $exit_code $last_words
018 function die() {
019     result=$1
020     shift
021     printf "%s\n" "$*" >&2
022     exit $result
023 }
024
025
026 function usage() {
027     die 1 'Try to run "vbak help [-t] for help.'
028 }
029
030
031 function show_help() {
032     if [ -z $1 ]; then
033         echo "Usage: qbak [COMMAND] [OPTION] ..."
034         echo "Commands are:"
035         echo -e "\thelp\tadd\tremove\tupdate"
036         echo -e "\tlist\tfiles\tclear\tcheckout/co"
037         echo
038         echo 'See more info: "vbak help -t"'
039     elif [ $1 == "-t" ]; then
040         echo "We have only *one* option: '-t'"
041         echo "Please put the '-t' option just after the COMMAND."
042         echo
043         echo "Command HELP can be with '-t', or without."
044         echo "$ vbak help"
045         echo "$ vbak help -t"
046         echo
047         echo "Command LIST and FILES can use '-t' option with its value, or none."
048         echo "$ vbak list -t emacs"
049         echo "$ vbak files"
050         echo
051         echo "Command REMOVE, UPDATE and can have '-t' option with its value, "
052         echo " or alternatively have its arguments."
053         echo "$ vbak remove .bashrc .lftp"
054         echo "$ vbak update -t network"
055         echo
056         echo "Command ADD must have its arguments."
057         echo "You can also use '-t' option with its *only* one value."
058         echo "$ add .emacs .bashrc .mplayer/"
059         echo "$ add -t opera opera6.ini opera6.adr wand.dat usejs/"
060         echo
061         echo "Command CHECKOUT(or CO) and CLEAR can only use like:"
062         echo "$ vbak clear"
063         echo "$ vbak co -t rc.3"
064         echo
065     else
066         die 1 "Panic: Unrecognized option. Only you can use is '-t'."
067     fi
068     exit 0
069 }
070
071
072 # check_files $file1 $file2 ...
073 # Check if files exist, else create it.
074 function check_files() {
075     check=0
076     for file
077     do
078         [ -f "$file" ] && continue ||
079         touch "$file" || check=1
080     done
081     return $check
082 }
083
084
085 # Read the variable VBAK_OUT_DIR setting.
086 function check_config() {
087     out_dir=$(grep "$1" $2 | sed 's/^.*= *//')
088     return $out_dir
089 }
090
091
092 # Get the tag name and set TAGNAME
093 function get_tag_name() {
094     if [ "$1" == "-t" ]; then
095         if [ -f "$2" ]; then
096             die 1 "You should define the tag name after '-t'."
097         else
098             TAGNAME="$2"
099             export TAGNAME
100         fi
101     fi
102 }
103
104
105 # We will use the encoded file name as the backup file's name.
106 # e.g. /home/vvoody/dic.txt --> home-vvoody-dic.txt
107 function encode_file_name() {
108         #echo $1 >&2
109         tmp0=`echo $1 | sed -e 's/\-/\\\-/g'`
110         #echo $tmp0 >&2
111         tmp1=`echo $tmp0 | sed -e 's#/#\-#g'`
112         #echo $tmp1 >&2
113         tmp2=`echo $tmp1 | sed -e 's/^\-//g'`
114         echo $tmp2
115         return 0
116 }
117
118
119 # .emacs -> /home/vvoody/.emacs
120 # Called by do_add and case
121 function full_file_name() {
122     f_name=""
123     foo=$(echo "$1" | sed -e 's/\/$//g')
124     # no '/' tail
125     if echo "$foo" | egrep "^/" >/dev/null ; then
126         f_name="$foo"
127     else
128         f_name="$PWD/${foo}"
129     fi
130     echo "$f_name"
131 }
132
133
134 # remove_line which_line
135 # called by do_remove and do_add
136 # This is too bad and ugly, I wanna use sed!
137 function remove_line() {
138     tmp=$(mktemp /tmp/vbak.$RANDOM.XXXXXXX) || return 2
139     egrep -v "$1" "$list_file" > $tmp
140     cat $tmp > "$list_file"
141 }
142
143
144 # Backup the files/dirs, and add them to the file.list
145 function do_add() {
146     full_name=$(full_file_name "$1")
147     # Maybe you are adding a file which already backuped.
148     egrep "$full_name" "$list_file"
149     if [ $? -eq 0 ]; then
150         echo -n "You have already backuped this file, backup again?(y/n)"
151         read y_or_n
152         if [ $y_or_n = "y" ]; then
153             remove_line "$full_name";
154         else
155             return 0
156         fi
157     fi
158
159
160     # backup( copy directly to $VBAK_OUT_DIR), add file information to file.list
161     if [ ! -z "$full_name" ]; then
162         echo "$full_name"
163         name=$(encode_file_name "$full_name") || return 1
164         echo $name
165         cp -rf "$full_name" "$VBAK_OUT_DIR/$name" || return 2
166         echo "$full_name" "@${TAGNAME}@" >> "$list_file" || return 3
167     else
168         die 4 "Backup failed!"
169     fi
170     return 0
171 }
172
173
174 # backuped files in the VBAK_OUT_DIR
175 # do_list [-t TAG]
176 function do_list() {
177     if [ -z "$TAGNAME" ]; then
178         tmp="$list_file"
179         sed -i 's/@.*@//g' "$tmp"
180 #       ls -1 -t $VBAK_OUT_DIR | egrep -v "file.list"
181     else
182         tmp=$(mktemp /tmp/vbak.$RANDOM.XXXXXXX) || return 2
183         egrep "$TAGNAME" "$list_file" | sed 's/@.*@//g' > $tmp
184     fi
185     while read line
186     do
187         file_bak_name=$(encode_file_name "$line") || return 3
188         if [ -e "${VBAK_OUT_DIR}/${file_bak_name}" ]; then
189             echo "$file_bak_name"
190         else
191             echo -n "$file_bak_name "
192             echo -e ${red}"*MISSED!*"${clr_normal}
193         fi
194     done < "$tmp"
195     return $?
196 }
197
198
199 # The genuine files
200 # do_files [-t TAG]
201 function do_files() {
202     if [ -z "$TAGNAME" ]; then
203         cat "$list_file" | sed 's/@.*@//g' || return 1
204     else
205         cat "$list_file" | egrep "@${TAGNAME}@" | sed 's/@.*@//g' || return 2
206     fi
207     return 0
208 }
209
210
211 # do_remove $file
212 function do_remove() {
213     # remove file record from file.list
214     # I need sed...
215     egrep "$1" "$list_file" > /dev/null
216     if [ $? -eq 0 ]; then
217     # remove backuped file from $VBAK_OUT_DIR
218         file_bak_name=$(encode_file_name "$1")
219         rm -rf "${VBAK_OUT_DIR}/${file_bak_name}"
220         remove_line "$1";
221     else
222         die 1 "$1 not backuped!"
223     fi
224 }
225
226
227 # do_update_dir $my_full_dir_path $orgin_full_bak_path
228 do_update_dir() {
229 #    echo "/xx/$(basename "$2")"
230     for f in "$1"/*; do
231         f_img="${2}/$(basename "$f")"
232         if [ "$f" -nt "$f_img" ]; then
233             if [ -d "$f" ]; then
234                 rm -rf "$f_img"
235             fi
236             cp -rf "$f" "$f_img"
237             echo -n "$f "
238             echo -e ${blue}"*UPDATED!*"${clr_normal}
239         else
240             if [ -d "$f" ]; then
241                 do_update_dir "$f" "$f_img";
242             fi
243         fi
244     done
245 }
246
247
248 # do_update $file
249 function do_update() {
250     # If the file is newer than the backuped file,
251     # then we will update it.
252     egrep "$1" "$list_file" > /dev/null
253     if [ $? -eq 0 ]; then
254         file_bak_name="$(encode_file_name "$1")"
255         if [ "$1" -nt "${VBAK_OUT_DIR}/${file_bak_name}" ]; then
256             if [ -d "$1" ]; then
257                 rm -rf "${VBAK_OUT_DIR}/${file_bak_name}"
258             fi
259             cp -rf "$1" "${VBAK_OUT_DIR}/${file_bak_name}"
260             echo -n "${1} "
261             echo -e ${blue}"*UPDATED!*"${clr_normal}
262         else
263             if [ -d "$1" ]; then
264                 do_update_dir "$1" "${VBAK_OUT_DIR}/${file_bak_name}";
265             fi
266         fi
267     else
268         die 1 "${1} not backuped!"
269     fi
270 }
271
272
273 # checkout a group of files with TAGNAME
274 function do_checkout() {
275     egrep "@${TAGNAME}@" "$list_file" > /dev/null
276     if [ $? -eq 0 ]; then
277         tmp=$(mktemp /tmp/vbak.$RANDOM.XXXXXXX) || return 2
278         egrep "@${TAGNAME}@" "$list_file" | sed 's/@.*@//g' > $tmp
279         local let counter=0
280         while read line
281         do
282             file_bak_name=$(encode_file_name "$line")
283             file_base_name=$(basename "$line")
284             if [ -e "${VBAK_OUT_DIR}/${file_bak_name}" ]; then
285                 let ++counter
286                 cp -rf "${VBAK_OUT_DIR}/${file_bak_name}" "./$file_base_name"
287             else
288                 echo -n "${file_bak_name} "
289                 echo -e ${red}"*missed!*"${clr_normal}
290             fi
291         done < $tmp
292     else
293         die 1 "No files checkouted!"
294     fi
295     echo "${counter} file(s) checkouted!"
296 }
297
298
299 # Empty the VBAK_OUT_DIR
300 # do_clear
301 function do_clear() {
302     echo "We will remove all backuped files and clear up the file.list"
303     echo -n "Are you sure? "
304     read y_or_n
305     if [ $y_or_n == "y" ]; then
306         rm -rf $VBAK_OUT_DIR/*
307     else
308         return 1
309     fi
310     return 0
311 }
312
313
314 ##### MAIN #####
315 if [ $# = 0 ]; then
316     usage
317 fi
318
319
320 rcfile="$HOME/.vbakrc"
321 export rcfile
322 default_out_dir="$HOME/.vbak"
323
324
325 check_files $rcfile || die $? "Panic: I don't hope we will reach here."
326
327
328 VBAK_OUT_DIR=$(grep "VBAK_OUT_DIR" $rcfile | sed 's/^.*=//')
329 if [ -z "$VBAK_OUT_DIR" ]; then
330     VBAK_OUT_DIR=$default_out_dir
331 fi
332
333
334 if ! echo $VBAK_OUT_DIR | egrep "^\/"; then
335     VBAK_OUT_DIR="$HOME/$VBAK_OUT_DIR"
336 fi
337
338
339 export VBAK_OUT_DIR
340
341
342 if [ ! -d "$VBAK_OUT_DIR" ]; then
343     mkdir -p "$VBAK_OUT_DIR"
344 fi
345
346
347 list_file="$VBAK_OUT_DIR/file.list"
348 check_files "$list_file"
349 export list_file
350
351
352 # Make error info more clearly.
353 red='\e[0;31;1m'
354 blue='\e[0;34;1m'
355 green='\e[0;32;1m'
356 clr_normal='\e[0m'
357
358
359 case "$1" in
360     help)
361         help_opt=$2
362         show_help $2;
363         ;;
364     list)
365         shift
366         get_tag_name "$@"
367         do_list;
368         ;;
369     files)
370         shift
371         get_tag_name "$@"
372         do_files;
373         ;;
374     add)
375         shift
376         get_tag_name "$@"
377         # obmit the option and tag name
378         if [ ! -z "$TAGNAME" ]; then
379             shift
380             shift
381         fi
382         for file in "$@"
383         do
384             echo -n "Add "
385             echo -e ${green}"$file"${clr_normal}
386             do_add "$file";
387         done
388         ;;
389     remove)
390         shift
391         get_tag_name "$@"
392         if [ ! -z "$TAGNAME" ]; then
393             tmp=$(mktemp "/tmp/vbak.$RANDOM.XXXXXXX") || return 2
394             egrep "@${TAGNAME}@" "$list_file" | sed 's/@.*@//g' > $tmp
395             while read line
396             do
397                 do_remove "$line";
398             done < $tmp
399         else
400             for f in "$@"
401             do
402                 # full the file name
403                 full_name=$(full_file_name "$f")
404                 do_remove "$full_name";
405             done
406         fi
407         ;;
408     update)
409         shift
410         get_tag_name "$@"
411         # vbak update OR vbak update -t TAGNAME
412         if [[ ( -z "$1") || (! -z "$TAGNAME") ]]; then
413             tmp=$(mktemp "/tmp/vbak.$RANDOM.XXXXXXX") || return 2
414             if [ -z "$TAGNAME" ]; then
415                 sed 's/@.*@//g' "$list_file" > $tmp
416             else
417                 egrep "@${TAGNAME}@" "$list_file" | sed 's/@.*@//g' > $tmp
418             fi
419
420
421             while read line
422             do
423                 do_update "$line";
424             done < $tmp
425         else
426             for f in "$@"
427             do
428                 # full the file name
429                 full_name=$(full_file_name "$f")
430                 do_update "$full_name";
431             done
432         fi
433         ;;
434     check|co)
435         shift
436         get_tag_name "$@"
437         if [ -z "$TAGNAME" ]; then
438             die 1 "Don't leave checkout alone, give him '-t' and a tag name."
439         fi
440         do_checkout;
441         ;;
442     clear)
443         do_clear;
444         ;;
445     *)
446         echo "Unknown command!" >&2
447         usage;;
448 esac


所有评论,共2条:( 我也来说两句)

1
vvoody 1年前 回复
0
0
看来没人需要哦。。。
2
0
0
我倒是喜欢这样的工具,可惜在win平台干活  

发表评论

注册登录后再发表评论