zoukankan      html  css  js  c++  java
  • shell小工具:findstr 和 findfile

    Linux下常用find+grep的组合来查找字符串或文件,但每次都要输入很长的命令,很是麻烦。下面的两个shell脚本类似对find+grep的组合命令的包装,可用于简单快速地从指定文件夹下查找字符串、宏定义、struct、class、typedef声明、以及查找指定文件。

    1、查找字符串、宏、结构体、类、typedef语句shell脚本(findstr):

    #! /bin/bash
    
    Usage()
    {
        echo "Usage: ${0##*/} [option] [path] search-content"
        echo "[Options]:"
        echo "  -S,--string               search string"
        echo "  -m,--macro                search macro define"
        echo "  -t,--typedef              search typedef statement"
        echo "  -c,--class                search class declare"
        echo "  -s,--struct               search class declare"
        echo "  -E,--extended-regexp      support grep extended regular expression"
        echo "  -i,--ignore-case          ignore search-content case"
        echo "  -e,--exclude-dir=dirlist  ignore directory whose name is in the excluding list(separated by :)"
        echo "  -h,--help                 display help information"
        echo "[Note]: If you don't specify path, default searching from current directory."
    }
    
    if [ $# -eq 0 ]; then
      Usage
      exit 1
    fi
    
    while [ $# -gt 0 ]; do
        case $1 in
        -*)
            case $1 in
            -S|--string)
                SEARCH_TYPE="string";;
            -m|--macro)
                SEARCH_TYPE="macro";;
            -t|--typedef)
                SEARCH_TYPE="typedef";;
            -c|--class)
                SEARCH_TYPE="class";;
            -s|--struct)
                SEARCH_TYPE="struct";;
            -E|--extended-regexp)
                GREP_EXT_REG_OPTION="-E";;
            -i|--ignore-case)
                GREP_IGNORE_CASE_OPTION="-i";;
            -e|--exclude-dir=*)
                if [ -n "$EXCLUDE_DIR_LIST" ]; then
                    echo "Invalid usage: double specify excluding dirs!"
                    exit 1
                fi
                if [ "$1" = "-e" ]; then
                    shift
                    if [ "${1:1:1}" = "-" ]; then
                        echo "Invalid usage: no dirname behind -e option!"
                        exit 1
                    else
                        EXCLUDE_DIR_LIST=":$1:"    # add : at both sides
                    fi
                else
                    EXCLUDE_DIR_LIST=":${1#*=}:"
                fi;;
            -h|--help)
                Usage
                exit 0;;
            *)
                echo "Invalid usage: unknown option $1!"
                exit 1;;
            esac ;;
        *)
            if [ -d "$1" ]; then
                if [ -z "$SEARCH_PATH" ]; then
                    SEARCH_PATH="$1"
                elif [ -z "$SEARCH_CONTENT" ]; then
                    SEARCH_CONTENT="$1"
                else
                    echo "Invalid usage: too many directory parameters!"
                    exit 1
                fi
            elif [ -z "$SEARCH_CONTENT" ]; then
                SEARCH_CONTENT="$1"
            else
                echo "Invalid usage: too many search-content parameters!"
                exit 1
            fi ;;
        esac
        shift
    done
    
    GREP_EXTRAL_OPTION="-n -H --color $GREP_EXT_REG_OPTION $GREP_IGNORE_CASE_OPTION"
    
    if [ -z $SEARCH_TYPE ]; then
        SEARCH_TYPE="string"
    fi
      
    if [ -z "$SEARCH_CONTENT" ]; then
        # perhaps the content to be searched is a path-style name, and not specify path parameter
        if [ -n "$SEARCH_PATH" ]; then
            SEARCH_CONTENT="$SEARCH_PATH"
            SEARCH_PATH="."
        else
            echo "Invalid usage: no search-content parameter!"
            exit 1
        fi
    fi
    
    if [ -z "$SEARCH_PATH" ]; then
        SEARCH_PATH="."
    fi
    
    SearchString()
    {
        # ignore /dev direcotry
        if [ "${PWD:0:4}" = "/dev" ]; then
            echo -e "\e[31mWarning:\e[m\e[33m ignored direcotry $PWD\e[m"
            return 
        fi
        for file in `ls`; do
            if [ -d $file ]; then
                # prevent symbol link which links to its parent directory (lineal consanguinity)
                if [ -L $file ]; then
                    FUN_SS_BASE_PWD_P=$(pwd -P)
                    FUN_SS_SUBDIR_PWD_P=$(cd ./$file; pwd -P)
                    if [ "${FUN_SS_BASE_PWD_P#$FUN_SS_SUBDIR_PWD_P}" != "${FUN_SS_BASE_PWD_P}" ]; then
                        continue
                    fi
                fi
                if [ "${EXCLUDE_DIR_LIST/:$file:/}" != "${EXCLUDE_DIR_LIST}" ]; then
                    continue
                fi
                cd ./$file # add "./" for those special directories whose name begin with "-"
                SearchString
                cd ..
                continue
            fi
            if [ ! -f $file -o ! -r $file ]; then
                echo -e "\e[31mWarning:\e[m\e[33m ignored file $PWD/$file\e[m"
            fi
            if grep $GREP_EXTRAL_OPTION "$SEARCH_CONTENT" "`pwd`/$file" ; then
                let "SEARCH_MATCH_COUNT+=1"
            fi
        done
    }
    
    Search()
    {
        # ignore /dev direcotry
        if [ "${PWD:0:4}" = "/dev" ]; then
            echo -e "\e[31mWarning:\e[m\e[33m ignored direcotry $PWD\e[m"
            return 
        fi
        for file in `ls`; do
            if [ -d $file ]; then
                # prevent symbol link which links to its parent directory (lineal consanguinity)
                if [ -L $file ]; then
                    FUN_S_BASE_PWD_P=$(pwd -P)
                    FUN_S_SUBDIR_PWD_P=$(cd ./$file; pwd -P)
                    if [ "${FUN_S_BASE_PWD_P#$FUN_S_SUBDIR_PWD_P}" != "${FUN_S_BASE_PWD_P}" ]; then
                        continue
                    fi
                fi
                if [ "${EXCLUDE_DIR_LIST/:$file:/}" != "${EXCLUDE_DIR_LIST}" ]; then
                    continue
                fi
                cd $file
                Search
                cd ..
                continue
            fi
            
            if [ ! -f $file -o ! -r $file ]; then
                echo -e "\e[31mWarning:\e[m\e[33m ignored file $PWD/$file\e[m"
            fi
            
            case $SEARCH_TYPE in
            macro)
                if grep $GREP_EXTRAL_OPTION "#[[:space:]]*define[[:space:]]*$SEARCH_CONTENT" "`pwd`/$file" ; then
                    let "SEARCH_MATCH_COUNT+=1"
                fi;;
            typedef)
                if grep $GREP_EXTRAL_OPTION "typedef.*$SEARCH_CONTENT" "`pwd`/$file" ; then
                    let "SEARCH_MATCH_COUNT+=1"
                fi;;
            class)
                if grep $GREP_EXTRAL_OPTION "class.*$SEARCH_CONTENT" "`pwd`/$file" ; then
                    let "SEARCH_MATCH_COUNT+=1"
                fi;;
            struct)
                if grep $GREP_EXTRAL_OPTION "struct.*$SEARCH_CONTENT" "`pwd`/$file" ; then
                    let "SEARCH_MATCH_COUNT+=1"
                fi;;
            *)
                if grep $GREP_EXTRAL_OPTION "$SEARCH_CONTENT" "`pwd`/$file" ; then
                    let "SEARCH_MATCH_COUNT+=1"
                fi;;
            esac
        done
    }
    
    pushd $SEARCH_PATH > /dev/null
    SEARCH_MATCH_COUNT=0
    if [ "$SEARCH_TYPE" = "string" ]; then
        SearchString
    else
        Search
    fi
    if [ $SEARCH_MATCH_COUNT -lt 1 ]; then
        echo -e "No $SEARCH_TYPE matches \033[40;31m$SEARCH_CONTENT\033[0m in \033[40;31m$SEARCH_PATH\033[0m directory and its sub-directory!"
    fi
    popd > /dev/null

    【说明】: (1) 此脚本不能跨行操作,因此对于定义为多行的(如:关键字class与其类名不在同一行的)查找内容会失效。
               (2) 此脚本考虑到效率问题,对符号链接若有死循环支持不够,只支持类似“直系血亲”的死循环检测。(后面的findfile脚本中SearchFile2提供了一种检测符号链接若有死循环的方法,不过效率不高,默认情况也不使用它。)

    2、查找文件shell脚本(findfile):

    #!/bin/bash
    
    Usage()
    {
        echo "Usage: ${0##*/} [option] [path] filename"
        echo "  -a,--absolute  dispaly absolute path (default)"
        echo "  -r,--relative  dispaly relative path"
        echo "  -e,--exact     the filename must be exactly matches"
        echo "  -h,--help      display this information"
        echo "[Note]: If you don't specify any option, -a will be used by default."
    }
    
    if [ $# -eq 0 ]; then
        echo "Invalid usage: no filename specified!"
        exit 1
    fi
    
    while [ $# -gt 0 ]; do
        case $1 in
        -*)
            # ignore duplicated and conflicted options
            case $1 in
            -a|--absolute)
                FLAG_ABSOLUTE_PATH="true"
                ;;
            -r|--relative)
                FLAG_ABSOLUTE_PATH="false"
                ;;
            -e|--exact)
                FLAG_EXACTLY_MATCH="true"
                ;;
            -h|--help)
                Usage
                exit 0
                ;;
            *)
                echo "Invalid usage: unknown option $1!"
                exit 1
                ;;
            esac ;;
        *)
            if [ -d "$1" ]; then
                if [ -z "$SEARCH_PATH" ]; then
                    SEARCH_PATH="$1"
                elif [ -z "$SEARCH_FILE" ]; then
                    SEARCH_FILE="$1"
                else
                    echo "Invalid usage: too many directory parameters!"
                    exit 1
                fi
            elif [ -z "$SEARCH_FILE" ]; then
                SEARCH_FILE="$1"
            else
                echo "Invalid use: too many filename parameters!"
                exit 1
            fi
            ;;
        esac
        shift
    done
    
    if [ -z $FLAG_ABSOLUTE_PATH ]; then
        FLAG_ABSOLUTE_PATH="true"
    fi
    
    if [ -z "$SEARCH_FILE" ]; then
        # perhaps the filename to be searched is a path-style name, and not specify path parameter
        if [ -n "$SEARCH_PATH" ]; then
            SEARCH_FILE="$SEARCH_PATH"
            SEARCH_PATH="."
        else
            echo "Invalid usage: no filename specified!"
            exit 1
        fi
    fi
    
    if [ -z "$SEARCH_PATH" ]; then
      SEARCH_PATH="."
    fi
    
    SearchFile()
    {
        for file in `ls`; do
            if [ -d $file ]; then
                # prevent symbol link which links to its parent directory (lineal consanguinity)
                if [ -L $file ]; then
                    FUN_SF_BASE_PWD_P=$(pwd -P)
                    FUN_SF_SUBDIR_PWD_P=$(cd ./$file; pwd -P)
                    if [ "${FUN_SF_BASE_PWD_P#$FUN_SF_SUBDIR_PWD_P}" != "${FUN_SF_BASE_PWD_P}" ]; then
                        continue
                    fi
                fi
    
                if [ "$FLAG_EXACTLY_MATCH" = "true" ]; then
                    if [ "$file" = "$SEARCH_FILE" ]; then
                        echo -e "$PWD/\e[34m$file\e[m"
                    fi
                elif [ "${file/$SEARCH_FILE/}" != "${file}" ]; then
                    echo -e "$PWD/${file/$SEARCH_FILE/\e[34m$SEARCH_FILE\e[m}"
                fi
                
                cd ./$file
                SearchFile
                cd ..
                continue
            fi
            
            if [ "$FLAG_EXACTLY_MATCH" = "true" ]; then
                if [ "$file" = "$SEARCH_FILE" ]; then
                    echo -e "$PWD/\e[34m$file\e[m"
                fi
            elif [ "${file/$SEARCH_FILE/}" != "$file" ]; then
                echo -e "$PWD/${file/$SEARCH_FILE/\e[34m$SEARCH_FILE\e[m}"
            fi
        done
    }
    
    cd $SEARCH_PATH
    SearchFile
    
    ## PHYSICAL_PATH_LIST must be initialized as :$(cd $SEARCH_PATH; pwd -P): before calling SearchFile2()
    ## considered the case: dead loop of symbol link
    #SearchFile2()
    #{
    #    for file in `ls`; do
    #        if [ -d $file ]; then
    #            cd ./$file
    #            FUN_SF_SON_PWD_P=$(pwd -P)
    #            if [ "${PHYSICAL_PATH_LIST/:$FUN_SF_SON_PWD_P:/}" != "${PHYSICAL_PATH_LIST}" ]; then
    #                cd ..
    #                continue
    #            fi
    #            PHYSICAL_PATH_LIST=${PHYSICAL_PATH_LIST}${FUN_SF_SON_PWD_P}:
    #
    #            if [ "$FLAG_EXACTLY_MATCH" = "true" ]; then
    #                if [ "$file" = "$SEARCH_FILE" ]; then
    #                    echo -e "$PWD/\e[34m$file\e[m"
    #                fi
    #            elif [ "${file/$SEARCH_FILE/}" != "${file}" ]; then
    #                echo -e "$PWD/${file/$SEARCH_FILE/\e[34m$SEARCH_FILE\e[m}"
    #            fi
    #            
    #            SearchFile2
    #            PHYSICAL_PATH_LIST=${PHYSICAL_PATH_LIST%:*:}:
    #            cd ..
    #            continue
    #        fi
    #        
    #        if [ "$FLAG_EXACTLY_MATCH" = "true" ]; then
    #            if [ "$file" = "$SEARCH_FILE" ]; then
    #                echo -e "$PWD/\e[34m$file\e[m"
    #            fi
    #        elif [ "${file/$SEARCH_FILE/}" != "$file" ]; then
    #            echo -e "$PWD/${file/$SEARCH_FILE/\e[34m$SEARCH_FILE\e[m}"
    #        fi
    #    done
    #}
    #
    #cd $SEARCH_PATH
    #PHYSICAL_PATH_LIST=:$(cd $SEARCH_PATH; pwd -P):
    #SearchFile2
    #
    ## The following implement has some questions on some platforms when search from /sys direcotry due to the use of -L option,
    ## but if not using -L option, it will ignored the symbol link which links to a direcotry 
    #SearchFile3()
    #{
    #    # In some systems, find not support -L option (find: invalid predicate '-L')
    #    find -L /usr -maxdepth 1 -name tmp > /dev/null 2>&1
    #    if [ $? -eq 0 ]; then
    #        FUN_SF_FIND_L_OPTION="-L"
    #    else
    #        FUN_SF_FIND_L_OPTION=""
    #        echo -e "\e[31mWarning:\e[m\e[33m find command doesn't support -L option, it will not enter into symbol link direcotry to search.\e[m"
    #    fi
    #    
    #    if [ "$FLAG_ABSOLUTE_PATH" = "true" ]; then
    #        cd $SEARCH_PATH
    #        FUN_SF_CURRENT_PATH=${PWD%/}
    #        find $FUN_SF_FIND_L_OPTION . -type f | grep $SEARCH_FILE | sed "s,\./,$FUN_SF_CURRENT_PATH,g" | grep --color $SEARCH_FILE
    #    else
    #        find $FUN_SF_FIND_L_OPTION $SEARCH_PATH -type f | grep --color $SEARCH_FILE
    #    fi
    #}
    #
    #SearchFile3
  • 相关阅读:
    [主席树][学习笔记]
    [bzoj2588][ Count on a tree]
    [bzoj3524][Couriers]
    [luogu3834][可持久化线段树 1(主席树)]
    [luogu3810][bzoj3262][陌上花开]
    [树套树][学习笔记]
    [luogu4556][Vani有约会]
    [线段树合并][学习笔记]
    [hdu6183][Color it]
    [动态开点线段树][学习笔记]
  • 原文地址:https://www.cnblogs.com/opangle/p/2595439.html
Copyright © 2011-2022 走看看