shell脚本(傻瓜式处理文件到指定分类)
前言
每一到两周,我大概会新增十多个甚至更多的资料文件,都是些最近遇到的一些问题的总结或者相关技术文档,但是资料都是在公司电脑上,拷贝到自己电脑上后,又得一个个去找一个这个应该放到哪个分类,个人感觉很麻烦。
傻瓜式处理文件脚本
为了解决困扰俺的这个问题,我想到了一个比较笨的解决办法,用脚本解决,但是这样就做出了一些牺牲,比如
- 脚本里规定了文件夹分类的命名方式为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月
shell脚本(傻瓜式处理文件到指定分类)的更多相关文章
- 如何使用shell脚本快速排序和去重文件数据
前面写过一篇通过shell脚本去重10G数据的文章,见<用几条shell命令快速去重10G数据>.然而今天又碰到另外一个业务,业务复杂度比上次的单纯去重要复杂很多.找了很久没有找到相应的办 ...
- [ Shell ] 通过 Shell 脚本导出 GDSII/OASIS 文件
https://www.cnblogs.com/yeungchie/ 常见的集成电路版图数据库文件格式有 GDSII 和 OASIS,virtuoso 提供了下面两个工具用来在 Shell 中导出版图 ...
- Centos7下crontab+shell脚本定期自动删除文件
问题描述: 最近有个需求,就是rsync每次同步的数据量很多,但是需要保留的数据库bak文件 保留7天就够了,所以需要自动清理文件夹内的bak文件 解决方案: 利用shell脚本来定期删除文件夹内的任 ...
- Shell脚本实现每个工作日定时执行指定程序
我们可能会遇到这样的情景:必须在每个工作日定时执行Linux服务器上的某个程序.那么有没有办法实现这一功能呢?答案是肯定的.我们可以运用Shell脚本简单实现这一功能. 原理很简单,Shell脚本内部 ...
- Shell脚本使用汇总整理——文件夹及子文件备份脚本
Shell脚本使用汇总整理——文件夹及子文件备份脚本 Shell脚本使用的基本知识点汇总详情见连接: https://www.cnblogs.com/lsy-blogs/p/9223477.html ...
- shell脚本实现读取一个文件中的某一列,并进行循环处理
shell脚本实现读取一个文件中的某一列,并进行循环处理 1) for循环 #!bin/bash if [ ! -f "userlist.txt" ]; then echo &qu ...
- Shell脚本对Linux进行文件校验
Shell脚本对Linux进行文件校验 一.需求 有客户等保需求对文件一致性进行校验,想到利用md5sum工具,因此写脚本来对文件进行自定义扫描,后期可以利用其进行校验,快速校验文件发现变更的文件,一 ...
- shell脚本:变量,文件判断,逻辑运算等纪要
shell脚本中的变量定义,引用各有不同的方式,除此之外,很常用的有文件属性判断,逻辑运算,数值运算等,下面记录一下它们的属性作用 变量 shell变量的定义分为两种:一种是直接赋值定义,另一种是嵌套 ...
- Shell脚本 | 抓取log文件
在安卓应用的测试过程中,遇到 Crash 或者 ANR 后,想必大家都会通过 adb logcat 命令来抓取日志定位问题.如果直接使用 logcat 命令的话,默认抓取出的 log 文件包含安卓运行 ...
随机推荐
- URAL 1741 Communication Fiend(最短路径)
Description Kolya has returned from a summer camp and now he's a real communication fiend. He spends ...
- Qscintilla2编译使用
Qscintilla2的下载地址: https://github.com/josephwilk/qscintilla https://riverbankcomputing.com/software/q ...
- penLDAP学习笔记
LDAP协议 目录是一组具有类似属性.以一定逻辑和层次组合的信息.常见的例子是通讯簿,由以字母顺序排列的名字.地址和电话号码组成.目录服务是一种在分布式环境中发现目标的方法.目录具有两个主要组成部分: ...
- Mybatis学习系列(三)动态SQL
在mapper配置文件中,有时需要根据查询条件选择不同的SQL语句,或者将一些使用频率高的SQL语句单独配置,在需要使用的地方引用.Mybatis的一个特性:动态SQL,来解决这个问题. mybati ...
- 学习MVC中出现的一个BUG
BUG描述:No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.S ...
- HDU B-Ignatius and the Princess IV
http://acm.hdu.edu.cn/showproblem.php?pid=1029 Problem Description "OK, you are not too bad, em ...
- WCF身份验证二:基于消息安全模式的自定义身份验证
使用X509证书进行身份验证应该说是WCF安全模型中最”正常”的做法, 因为WCF强制要求使用证书加密身份数据, 离开了证书, 所有的身份验证机制拒绝工作, WCF支持的身份验证机制也相当复杂, 这里 ...
- systemtap get var of the tracepoing
kernel.trace("sched_switch") func:func:perf_trace_sched_stat_template get the function in ...
- React & shit Antd
React & shit Antd https://ant.design/components/tooltip-cn/ https://ant.design/components/tag-cn ...
- [剑指Offer] 20.包含min函数的栈
题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. [思路1]两个栈Stack和Min,Stack为当前栈中元素,Min为与Stack中元素一一对应的当前栈最小值. cl ...