前言
每一到两周,我大概会新增十多个甚至更多的资料文件,都是些最近遇到的一些问题的总结或者相关技术文档,但是资料都是在公司电脑上,拷贝到自己电脑上后,又得一个个去找一个这个应该放到哪个分类,个人感觉很麻烦。
傻瓜式处理文件脚本
为了解决困扰俺的这个问题,我想到了一个比较笨的解决办法,用脚本解决,但是这样就做出了一些牺牲,比如
- 脚本里规定了文件夹分类的命名方式为nn##为前缀,否则就不把它当作分类,n是数字0-9,例如我的:
00##linux
00##fedora
00##ubuntu
00##工具
01##windows
02##mine
03##电子书
- 同时也规定了新增文件或者文件夹命名要以将要移到哪个文件夹分类名为前缀,比如新增一个文件automake.doc,他属于linux下的工具,那么命名时就以 工具aotumake.doc 如果发生冲突,比如在windows下也有工具这个文件夹分类,那么会提示你选择一个。
这是傻瓜式的处理啦,我也考虑过智能的,但是智能的可能会导致很多冲突,经常会提醒你选一个,那样反而麻烦,或许有更好的智能处理,希望大家提示下我,因为我对智能匹配不怎么了解,现在是否有这方面相关的开源代码也不知道
先把脚本列出来啦,大家多多指点下我啦,脚本中哪些处理的不当等都可以留言。
我用的环境是: 虚拟机fedora里运行程序来处理windows的磁盘
#!/bin/bash
#限制: 分类的文件夹必须是两位数字然后##开头,不能多也不能少,如00##linux
#禁止文件名中有"、@,这些内部在处理包含空格的文件时要用到
unset cmd_cnt
unset cmds
unset err_cnt
unset err_log
unset dst_path
unset dirs
bin_path="`which $0`"
DEFAULT_CACHE_FILE="${bin_path%/*}/.cache.log"
DEFAULT_ERR_INFO_FILE="${bin_path%/*}/.error.log"
DEFAULT_RIG_INFO_FILE="${bin_path%/*}/.right.log"
DEFAULT_TMP_FILE="${bin_path%/*}/.tmp.log"
cmd_cnt=0
err_cnt=0
HELPFLAG=0
EXITFLAG=0
CACHEFLAG=0
TMPFLAG=0
CLEANFLAG=0
UPDATEFLAG=0
DISPLAY=0
trap int_handle INT
int_handle ()
{
echo "get int signal"
rm -f $DEFAULT_ERR_INFO_FILE
rm -f $DEFAULT_RIG_INFO_FILE
EXITFLAG=1
event_handle
}
print_help ()
{
echo "Usage: $0 help Print help"
echo "Usage: $0 display Print the current classification of cache"
echo "Usage: $0 clean Clean the current classification of cache"
echo "Usage: $0 update dst_path Create or update classification cache by dst_path directory"
echo "Usage: $0 src_path Autoassign src_path directory with current classification cache"
echo "Usage: $0 src_path dst_path Autoassign src_path directory with classify directory dst_path and create cache by dst_path,"
echo " ${0//[a-z\/]/ } but premise is current classification of cache is not exist, otherwise, dst_path will be ignored"
}
do_update ()
{
if [ "$1" != "" ]; then
[ ! -d "$1" ] && echo "=============>"dst_dir: "$1" is invalid! && return 1
dst_path="$1"
else
if [ -s "$DEFAULT_CACHE_FILE" -a -r "$DEFAULT_CACHE_FILE" ]; then
dst_path="`head -n 1 $DEFAULT_CACHE_FILE | cut -d '\\' -f 2`"
[ ! -d "$dst_path" ] && echo "=============>"dst_dir: "$dst_path" is invalid! cache file error! do clean first! && return 1
else
echo "=============>update maybe $DEFAULT_CACHE_FILE is not exist!"
echo "=============>you should specify a directory, eg: $0 update dst_dir!"
return 1
fi
fi
rm -f $DEFAULT_CACHE_FILE
echo "update..."
collect_classify_info "$dst_path"
[ "$?" == 0 ] && create_cache "$dst_path" || return 1
echo "update ok!"
return 0
}
if_in_records ()
{
local arg1
[ "$cmd_cnt" == 0 ] && return 1
for i in `seq 0 $(($cmd_cnt-1))`
do
arg1=`echo ${cmds[$i]} | cut -d ' ' -f2`
arg1=${arg1:0:${#arg1}-1}
echo "$1" | grep -q "^$arg1.*/.*" && return 0
done
return 1
}
move_record ()
{
cmds[cmd_cnt]=mv\ "$1"\ "$2"
let cmd_cnt++
}
move_records ()
{
local i=0
local dir dirs
src=$1
echo -e "=============>path:$src \nfind dir in"
shift
dirs=($@)
for dir in ${dirs[@]}
do
echo -e "\t[$i] $dir"
let i++
done
read -p "=============>select one: " choice
if [ "$choice" -ge 0 -a "$choice" -lt $i ]; then
echo "=============>your choice is $choice ${dirs[$choice]}"
cmds[cmd_cnt]=mv\ "$src"\ "${dirs[$choice]}"
let cmd_cnt++
else
echo "=============>choice $choice wrong!"
err_record $src
fi 2> /dev/null
}
err_record ()
{
err_log[err_cnt]="$1"
let err_cnt++
}
exec_cmd ()
{
local cmd
for cmd in "${cmds[@]}"
do
arg1=`echo $cmd | cut -d ' ' -f2`
arg2=`echo $cmd | cut -d ' ' -f3`
arg1=${arg1//\"/}
arg2=${arg2//\"/}
opt1=$(basename $arg1)
opt2=$(basename $arg2)
lastname=${opt1#${opt2:4}}
[ "$lastname" == "" ] && echo "$arg1" is invalid! &&
echo "=============>mv" "${arg1//@/ }" "${arg2//@/ }"/"${lastname//@/ }" "failed!" \
| tee -a $DEFAULT_ERR_INFO_FILE && continue
mv "${arg1//@/ }" "${arg2//@/ }"/"${lastname//@/ }"
[ "$?" == 0 ] && echo "=============>mv" "${arg1//@/ }" "${arg2//@/ }"/"${lastname//@/ }" successed! \
| tee -a $DEFAULT_RIG_INFO_FILE || echo "=============>mv" "${arg1//@/ }" "${arg2//@/ }"/"${lastname//@/ }" failed!\
| tee -a $DEFAULT_ERR_INFO_FILE
done
}
print_autoassign_message ()
{
local err cmd
rm -f $DEFAULT_ERR_INFO_FILE
echo ------------------------error message------------------------
if [ "$err_cnt" -gt 0 ]; then
for err in ${err_log[@]}
do
echo ${err//@/ } | tee -a $DEFAULT_ERR_INFO_FILE
done
fi
echo -------------------------------------------------------------
echo ------------------------right message------------------------
if [ "$cmd_cnt" -gt 0 ]; then
for cmd in "${cmds[@]}"
do
echo move: ${cmd//@/ } #| tee -a $DEFAULT_RIG_INFO_FILE
done
fi
echo -------------------------------------------------------------
}
start_autoassign ()
{
items=`find "$1"/* 2>>$DEFAULT_TMP_FILE | sed 's/ /@/g' | sed 's/\(^.*$\)/"\1"/g'`
for item in $items
do
if_in_records "$item" && continue
tmpitem="`eval basename \$item`"
j=0
for i in `seq 0 $total`
do
tmpdir="`eval basename \${dirs[$i]}`"
echo "$tmpitem" | grep -q "^${tmpdir:4}" && itemdirs[j]=${dirs[$i]} && let j++
done
[ $j -eq 0 ] && err_record $item
[ $j -eq 1 ] && move_record "$item" "${itemdirs[0]}"
[ $j -gt 1 ] && move_records "$item" "${itemdirs[@]}"
done 2>>$DEFAULT_TMP_FILE
[ -s $DEFAULT_TMP_FILE ] && TMPFLAG=1 && return 1 || return 0
}
collect_classify_info ()
{
local i=0
local dir=
local err_flag=0
if [ -s "$DEFAULT_CACHE_FILE" -a -r "$DEFAULT_CACHE_FILE" ]; then
for dir in `cat $DEFAULT_CACHE_FILE`
do
[ "${dir:0:1}" == "\\" ] && continue
echo classify:"$dir"
dirs[i]="$dir"
let i++
done
else
for dir in `find "$1"/* -type d -name "[0-9][0-9]##[^0-9]*" 2>/dev/null | sed 's/ /@/g' | sed 's/\(^.*$\)/"\1"/g'`
do
echo classify:"$dir"
dirs[i]="$dir"
let i++
done
CACHEFLAG=1
fi
total=$((i-1))
if [ "$total" -gt 0 ];then
echo "=============>init success!"
return 0
else
echo "=============>init failed!"
EXITFLAG=1
return 1
fi
}
create_cache ()
{
local err_flag=0
if [ "$CACHEFLAG" == 1 ]; then
echo "\\$1" >> $DEFAULT_CACHE_FILE || err_flag=1
for i in `seq 0 $total`
do
echo "${dirs[$i]}" >> $DEFAULT_CACHE_FILE || err_flag=1
done
if [ "$err_flag" == 0 ]; then
echo "=============>create cache success!"
return 0
else
echo "=============>create cache failed!"
return 1
fi
fi
return 0
}
parse_argv ()
{
dst_path="$2"
if [ "$2" != "" -a "${2:0:1}" != '/' ]; then
dst_path="`pwd`/$2"
fi
case "$1" in
help)
HELPFLAG=1
EXITFLAG=1
return 1
;;
display)
DISPLAY=1
EXITFLAG=1
return 1
;;
clean)
CLEANFLAG=1
EXITFLAG=1
return 1
;;
update)
UPDATEFLAG=1
EXITFLAG=1
return 1
;;
*)
local need_num=0
if [ -s "$DEFAULT_CACHE_FILE" -a -r "$DEFAULT_CACHE_FILE" ]; then
[ ! -e "$1" ] && echo "parse argument file \"$1\" is not exist" && HELPFLAG=1 && EXITFLAG=1 && return 1
dst_path="`head -n 1 $DEFAULT_CACHE_FILE | cut -d '\\' -f 2`"
[ "$2" != "" ] && echo "read dst_path:$dst_path from cache file, ignore dst_dir:$2"
need_num=1
else
[ ! -e "$1" -o ! -e "$2" ] && echo "parse argument failed!" && HELPFLAG=1 && EXITFLAG=1 && return 1
need_num=2
fi
[ $# -lt "$need_num" ] && HELPFLAG=1 && EXITFLAG=1 && return 1
return 0
;;
esac
}
do_save ()
{
if [ ! -e "$1" ]; then
echo "=============>$1" is not exist
return 1
fi
local do_it=0
local filename="$2"
while :;
do
if [ -e "$filename" ]; then
read -p "=============>$2 is exist, Do you want to overwrite it or change filename? Y[y]/C[c]/N[n]" Yn
if [ "$Yn" == Y -o "$Yn" == y ] ; then
do_it=1
break
elif [ "$Yn" == C -o "$Yn" == c ] ; then
read -p "input filename ? " filename
else
break
fi
else
do_it=1
break
fi
done
[ "$do_it" == 1 ] && cp "$1" "$filename" && echo "save $filename successed!" && return 0 || return 1
}
autoassign_handle ()
{
local RET=0
if [ "$cmd_cnt" -gt 0 ]; then
read -p "do move ? Y[y]/N[n] " Yn
if [ "$Yn" == "Y" -o "$Yn" == "y" ] ; then
echo "start moving..."
exec_cmd
echo "move finished!"
fi
else
echo nothing need to move!
EXITFLAG=1
RET=1
fi
if [ -s $DEFAULT_ERR_INFO_FILE -a -r $DEFAULT_ERR_INFO_FILE ]; then
read -p "print error messages ? Y[y]/N[n] " Yn
if [ "$Yn" == Y -o "$Yn" == y ] ; then
echo -e "\n----------------------error messages----------------------------\n"
cat -n $DEFAULT_ERR_INFO_FILE
echo -e "\n----------------------------------------------------------------\n"
fi
read -p "save error messages to file ? Y[y]/N[n] " Yn
if [ "$Yn" == Y -o "$Yn" == y ] ; then
read -p "input filename ? " filename
do_save "$DEFAULT_ERR_INFO_FILE" "$filename"
fi
rm -f $DEFAULT_ERR_INFO_FILE
fi
if [ -s $DEFAULT_RIG_INFO_FILE -a -r $DEFAULT_RIG_INFO_FILE ]; then
read -p "print moved messages ? Y[y]/N[n] " Yn
if [ "$Yn" == Y -o "$Yn" == y ] ; then
echo -e "\n-----------------------moved messages---------------------------\n"
cat -n $DEFAULT_RIG_INFO_FILE
echo -e "\n----------------------------------------------------------------\n"
fi
read -p "save right messages to file ? Y[y]/N[n] " Yn
if [ "$Yn" == Y -o "$Yn" == y ] ; then
read -p "input filename ? " filename
do_save "$DEFAULT_RIG_INFO_FILE" "$filename"
fi
rm -f $DEFAULT_RIG_INFO_FILE
fi
return $RET
}
event_handle ()
{
echo "start event handle..."
if [ "$HELPFLAG" == 1 ]; then
HELPFLAG=0
echo "===============start================"
print_help
echo "================end================="
fi
if [ "$DISPLAY" == 1 ]; then
echo "===============start================"
DISPLAY=0
if [ -s "$DEFAULT_CACHE_FILE" -a -r "$DEFAULT_CACHE_FILE" ]; then
tail -n +2 $DEFAULT_CACHE_FILE
else
echo "=============>display maybe $DEFAULT_CACHE_FILE is not exist!"
fi
echo "================end================="
fi
if [ "$TMPFLAG" == 1 ]; then
TMPFLAG=0
echo "================error!!!============="
cat $DEFAULT_TMP_FILE
echo "====================================="
rm -f "$DEFAULT_TMP_FILE"
EXITFLAG=1
fi
if [ "$CLEANFLAG" == 1 ]; then
CLEANFLAG=0
rm -f $DEFAULT_CACHE_FILE
echo "clean ok!"
fi
if [ "$UPDATEFLAG" == 1 ]; then
UPDATEFLAG=0
do_update "$dst_path"
fi
echo "event handle finished!"
if [ "$EXITFLAG" == 1 ]; then
exit
fi
}
echo "start parse. argument: $@"
parse_argv "$@" || event_handle
echo "parse finished!"
echo "start collect classify info from $dst_path"
collect_classify_info "$dst_path" || event_handle
echo "collect finished!"
create_cache "$dst_path"
echo "start autoassign from ${1}"
start_autoassign "$1" || event_handle
echo "autoassign finished!"
print_autoassign_message#
echo "start autoassign handle"
autoassign_handle
echo "autoassign handle
体会
使用一段时间后,发现这种方式不太可行,除非你能接受所有文件及文件夹命令按上文所要求那样,之所以还保留这篇文章,也是期望某个高人能够有更好的想法提出。
完!
2012年12月