zoukankan      html  css  js  c++  java
  • shell脚本(傻瓜式处理文件到指定分类)

    前言

      每一到两周,我大概会新增十多个甚至更多的资料文件,都是些最近遇到的一些问题的总结或者相关技术文档,但是资料都是在公司电脑上,拷贝到自己电脑上后,又得一个个去找一个这个应该放到哪个分类,个人感觉很麻烦。

    傻瓜式处理文件脚本

      为了解决困扰俺的这个问题,我想到了一个比较笨的解决办法,用脚本解决,但是这样就做出了一些牺牲,比如

    1. 脚本里规定了文件夹分类的命名方式为nn##为前缀,否则就不把它当作分类,n是数字0-9,例如我的:
    00##linux
               00##fedora
               00##ubuntu
               00##工具
    01##windows
    02##mine
    03##电子书
    
    1. 同时也规定了新增文件或者文件夹命名要以将要移到哪个文件夹分类名为前缀,比如新增一个文件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 
    find dir in"
            shift
    
            dirs=($@)
            for dir in ${dirs[@]}
            do
                echo -e "	[$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 "
    ----------------------error messages----------------------------
    "
                    cat -n $DEFAULT_ERR_INFO_FILE
                    echo -e "
    ----------------------------------------------------------------
    "
                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 "
    -----------------------moved messages---------------------------
    "
                    cat -n $DEFAULT_RIG_INFO_FILE
                    echo -e "
    ----------------------------------------------------------------
    "
                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月

  • 相关阅读:
    FreePbx
    ntpdate和date
    Linux系统/dev/mapper目录浅谈
    利用rsync做全平台备份
    windows 共享给 linux
    Linux、UNIX设置开机自动运行命令
    JNU周练1019
    JNU周练1013
    2013/7/30 JNU周练
    二叉树遍历
  • 原文地址:https://www.cnblogs.com/rongpmcu/p/7662168.html
Copyright © 2011-2022 走看看