shell脚本实现遍历目录查找类和其所有的子类被调用的地方

4 篇文章 0 订阅
2 篇文章 0 订阅

1.目标和方案

目标:给定一个类名称,在一个目录下查找该类所有的直接和间接子类,并查找该类和其子类被调用的地方。

方案:第一步:遍历目录查找该类的所有子类。例如类名称为A,此时需要查找extends A的所有地方,取出子类名称B,再查询extends B出现的地方,获取到B的子类......以此递归找到所有的A的直接和间接子类,并将类A和其所有的子类存入一个文件final_class_name.txt中。第二步:在指定目录下遍历final_class_name.txt中的类名称,查询类名称在目录下被调用的文件路径,并存入到final_result.txt文件中。

2.代码

shell脚本文件search_classname.sh代码如下,该脚本执行需要两个参数,第一个参数为目录,第二个参数为类名称。

#!/bin/bash

dir=$1
keyword=$2
#先删除搜索过程中会用到的两个文件final_class_name.txt和final_result.txt
rm -rf final_class_name.txt
rm -rf final_result.txt
#判断该路径是否存在,并且是目录,不存在输出提示
test ! -d $dir && echo -e "The $dir is not exist in your system.\n\n" && exit 0

echo -e "\n---------------start search $keyword and it's subclass.......\n"

#统计文件个数
file_count=0
#递归查看所有目录,即最深路径,不显示空行
file_list=`ls -R $dir 2> /dev/null | grep -v '^$'`

#step 1.找出所有和keyword相关的直接继承类和间接继承类,并存放在一个keywords文件中

echo $keyword >> final_class_name.txt
source class_function
search_all_class $1 $keyword

#step 2.遍历final_class_name.txt文件,查找这些相关类名所在的文件路径

#要遍历查询的类名文件
class_file=./final_class_name.txt
for line in $(cat $class_file)
do
    #显示要查询的类名
    #echo $line
    #调用search_classname脚本,传入目录路径和要查询的类名称
    source class_function
    search_class_path $dir $line
done
echo -e "\nSearch class and it's subclass Finished!\n"

以上代码中调用的一个函数search_all_class和search_class_path存放在class_function文件中,class_function文件代码如下:

function search_all_class()
{
    
    local dir=$1
    local extends="extends "
    local keyword=${extends}${2}
    #判断该路径是否存在,并且是目录,不存在输出提示
    test ! -d $dir && echo -e "The $dir is not exist in your system.\n\n" && exit 0

    #统计文件个数
    local file_count=0
    #1递归查看所有目录,即最深路径,不显示空行
    local file_list=`ls -R $dir 2> /dev/null | grep -v '^$'`
    for file_name in $file_list
    do
        #临时文件变量temp,将ls -R即file_list中的文件名中所有匹配:后接一个或多个任意字符(.代表任意字符,*代表0个或多个$代表行尾结束符)全局替换为无
        #简单的说,就是把file_name变量中的匹配:的行,将:后内容替换为空
        temp=`echo $file_name | sed 's/:.*$//g'`
        #如果临时文件变量temp是一个目录,而非文件,就将该目录赋值给cur_dir变量
        if [ "$file_name" != "$temp" ]; then
            local cur_dir=$temp
            #echo "-"$cur_dir #临时显示,调试用
        else
            #用file命令查看文件真身是否为ASCII text类型
            file_type=`file $cur_dir/$file_name | grep "text"`
            if [ "$file_type" != "" ]; then
                temp=`grep "$keyword" $cur_dir/$file_name 2> /dev/null`
                if [ "$temp" != "" ]; then
                    #echo $cur_dir/$file_name
                    #文件个数加1
                    let file_count++
                    #echo "temp1="$temp
                    #删除extends开始的后边内容
                    temp=${temp%extends*}
                    #echo "temp2="$temp
                    #删除class 结尾的前边内容太,此时,只剩下类名称了
                    temp=${temp#*class }
                    #echo "temp3="$temp

                    #final_class_name.txt用于最终的整体查找
                    echo $temp >> final_class_name.txt
                    search_all_class $dir $temp
                else
                    continue       
                fi
            fi
        fi
        
    done 
}

#$1为输入目录,$2为要查找的类名称
#找到所有的调用该类的地方,并将文件路径存储在final_result.txt中
function search_class_path()
{
    dir=$1
    keyword=$2
    #判断该路径是否存在,并且是目录,不存在输出提示
    test ! -d $dir && echo -e "The $dir is not exist in your system.\n\n" && exit 0

    #统计文件个数
    file_count=0
    #递归查看所有目录,即最深路径,不显示空行
    file_list=`ls -R $dir 2> /dev/null | grep -v '^$'`
    for file_name in $file_list
    do
        #临时文件变量temp,将ls -R即file_list中的文件名中所有匹配:后接一个或多个任意字符(.代表任意字符,*代表0个或多个$代表行尾结束符)全局替换为无
        #简单的说,就是把file_name变量中的匹配:的行,将:后内容替换为空
        temp=`echo $file_name | sed 's/:.*$//g'`
        #如果临时文件变量temp是一个目录,而非文件,就将该目录赋值给cur_dir变量
        if [ "$file_name" != "$temp" ]; then
            cur_dir=$temp
            #echo "-"$cur_dir #临时显示,调试用
        else
            #echo "file_name=$file_name"
            #用file命令查看文件真身是否为ASCII text类型
            file_type=`file $cur_dir/$file_name | grep "text"`
            if [ "$file_type" != "" ]; then
                temp=`grep $keyword $cur_dir/$file_name 2> /dev/null`
                if [ "$temp" != "" ]; then
                    echo $cur_dir/$file_name >> final_result.txt
                    #文件个数加1
                    let file_count++
                fi
            fi
        fi
    done
}

3.运行示例

执行脚本实例如下,第一个参数/home/zhuws/android8.1/j6-6a8.1/packages/apps/Bluetooth为需要查询的目录,第二个参数StateMachine为要查询的类名称。

./search_classname.sh /home/zhuws/android8.1/j6-6a8.1/packages/apps/Bluetooth StateMachine

执行完后,就会在同一个目录下看到下面两个文件,查看里边结果就可以了。

-rw-rw-r-- 1 zhuws zhuws  194 11月 15 16:28 final_class_name.txt
-rw-rw-r-- 1 zhuws zhuws 8565 11月 15 16:29 final_result.txt

4.一些总结

1)递归查询目录

        要遍历目录之前,先要查到目录下所有的子目录和文件有哪些,于是想到了ls命令。使用ls -R folder可以将目录下所有的子目录和文件都列出来,相当于我们编程中的“递归”实现。这块网上也参考了网上一篇博客的代码,具体忘记链接地址了。

2)shell中递归函数使用

shell中递归函数这块我写的时候遇到了个大坑:下层函数调用后把上层函数里的变量值给修改了,导致不能正常递归遍历。后来查找资料,终于知道递归函数中所有变量都要前边加上local,表示其范围是在当前函数内。参考了这篇文章https://www.crifan.com/linux_shell_recursive_function_variable_be_changed/

3)截取字符串

通过extends A查到了public class B extends A这样一行后,需要将里边的B截取出来。字符串接截取可以参考这个链接:https://www.cnblogs.com/zwgblog/p/6031256.html

------finish--------

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值