├── .idea ├── .gitignore ├── TinyImages.iml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── CompressImages.py ├── FindAllAPartFiles.py ├── FindAllImages.py ├── FindUnUseDefine.py ├── FindUnUseImage.py ├── FindUnUseResource.py ├── RepeatFileFindPro.py └── __pycache__ ├── FindAllAPartFiles.cpython-37.pyc └── FindAllImages.cpython-37.pyc /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Default ignored files 3 | /workspace.xml -------------------------------------------------------------------------------- /.idea/TinyImages.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CompressImages.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 图片批量压缩 3 | import tinify 4 | import os 5 | import os.path 6 | import shutil 7 | import sys 8 | import getopt 9 | import FindAllImages 10 | 11 | 12 | # 获取入参参数 13 | def getInputParm(): 14 | opts, args = getopt.getopt(sys.argv[1:], '-k:-f:-t:', ['key=', 'fromFilePath=', 'toFilePath:']) 15 | # 获取输入的参数 16 | for opt_name, opt_value in opts: 17 | if opt_name in ('-k', '--key'): 18 | tinifyKey = opt_value 19 | if opt_name in ('-f', '--fromFilePath'): 20 | fromFilePath = opt_value 21 | if opt_name in ('-t', '--toFilePath'): 22 | toFilePath = opt_value 23 | 24 | if len(tinifyKey) == 0 or len(fromFilePath) == 0 or len(toFilePath) == 0: 25 | print("\033[0;31;40m 请按照格式输入: python/python3 " + sys.argv[ 26 | 0] + " -k -f -t\033[0m") 27 | exit(1) 28 | 29 | if not os.path.exists(fromFilePath): 30 | print("\033[0;31;40m\t输入的压缩文件路径不存在\033[0m") 31 | exit(1) 32 | 33 | return tinifyKey, fromFilePath, toFilePath 34 | 35 | 36 | # tinify.key = "jSrjT94QC4f4Sdqn0JFTrclj2tbXxWh3" 37 | # fromFilePath = "/Users/a58/Desktop/Tools/TestFile" 38 | # toFilePath = "/Users/a58/Desktop/Tools/FinalFile" 39 | 40 | 41 | def compress(tinifyKey, fromFilePath, toFilePath, allFileNum): 42 | print("\n压缩中 ........") 43 | 44 | # 首先删除 toFilePath 文件下面的内容 45 | if os.path.exists(toFilePath): # 如果文件存在 46 | shutil.rmtree(toFilePath) 47 | os.mkdir(toFilePath) 48 | 49 | pngSum = 0 50 | jpgSum = 0 51 | toFileSize = 0 52 | hasOperateNum = 0 53 | failedImages = [] 54 | 55 | # 压缩图片的key 56 | tinify.key = tinifyKey 57 | 58 | for root, dirs, files in os.walk(fromFilePath): 59 | for name in files: 60 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 61 | # print("--- " + os.path.join(root, name)) 62 | # 获取文件名,扩展名 63 | fileName, fileSuffix = os.path.splitext(name) 64 | # 最终要保存的目标路径构造 root[len(fromFilePath):] 获取的是当前路径下面的子路径 65 | toFullPath = toFilePath + root[len(fromFilePath):] 66 | # 最终要保存的文件全路径 67 | toFullName = toFullPath + '/' + name 68 | # 如果文件不存在就创建文件 69 | if not os.path.exists(toFullPath): 70 | os.makedirs(toFullPath) 71 | 72 | # 如果扩展名是 png 或者是 jpg 的 再去压缩,其他的不管 73 | if fileSuffix == '.png' or fileSuffix == '.jpg': 74 | 75 | # 避免有的图片tinify解析不了 76 | try: 77 | # 使用 tinify 进行压缩和写入 78 | source = tinify.from_file(root + '/' + name) 79 | source.to_file(toFullName) 80 | 81 | except: 82 | # 图片压缩失败记录 83 | failedImages.append(name) 84 | # 并且原路拷贝回去 85 | shutil.copy2(root + '/' + name, toFullName) 86 | # 统计文件大小 87 | toFileSize = toFileSize + os.path.getsize(toFullName) 88 | else: 89 | print("*********当前压缩成功的图片 %s" % name) 90 | # 统计文件大小 91 | toFileSize = toFileSize + os.path.getsize(toFullName) 92 | # 压缩成功 93 | if fileSuffix == '.png': 94 | pngSum = pngSum + 1 95 | elif fileSuffix == '.jpg': 96 | jpgSum = jpgSum + 1 97 | 98 | 99 | else: 100 | # 非 png 和 jpg的文件,原路拷贝回去 101 | shutil.copy2(root + '/' + name, toFullName) 102 | 103 | # if name != '.DS_Store' and fileSuffix != '.json': 104 | # # 打印出当前是否有异常的文件 105 | 106 | # 统计文件大小 107 | toFileSize = toFileSize + os.path.getsize(toFullName) 108 | 109 | # 处理过的文件数量统计 110 | hasOperateNum = hasOperateNum + 1 111 | 112 | percent = hasOperateNum / allFileNum 113 | sys.stdout.write("\r# 已压缩png【%d 张】已压缩jpg【%d张】| 当前完成进度: %.1f %%" % (pngSum, jpgSum, percent * 100)) 114 | sys.stdout.flush() 115 | 116 | return pngSum, jpgSum, toFileSize, hasOperateNum, failedImages 117 | 118 | 119 | # 打印最终的处理结果 120 | def printOperateResult(oldPngSum, newPngSum, oldJpgSum, newJpgSum, fromFileSize, toFileSize, oldFileSum, newFileSum, 121 | failedImages): 122 | print("\n\n压缩完成 ........") 123 | print("png图片:压缩前【%d 张】成功压缩【%d 张】" % (oldPngSum, newPngSum)) 124 | print("jpg图片:压缩前【%d 张】成功压缩【%d 张】" % (oldJpgSum, newJpgSum)) 125 | print("压缩前图片总数【%d 张】成功压缩【%d 张】" % ((oldPngSum + oldJpgSum), (newPngSum + newJpgSum))) 126 | print("压缩前文件总数【%d 张】压缩后【%d 张】" % (oldFileSum, newFileSum)) 127 | 128 | # 压缩前和压缩后的文件大小对比 129 | unit = 'KB' 130 | fromFileSize = fromFileSize / float(1000) 131 | toFileSize = toFileSize / float(1000) 132 | if fromFileSize > 1000: 133 | fromFileSize = fromFileSize / float(1000) 134 | toFileSize = toFileSize / float(1000) 135 | unit = 'M' 136 | 137 | print("压缩前大小【%.2f %s】,压缩后大小【%.2f %s】" % (fromFileSize, unit, toFileSize, unit)) 138 | 139 | if len(failedImages) > 0: 140 | print("\n\033[0;31;40m【%d张】图片压缩失败---可能是因为tinify压缩失败,也可能是因为key超过使用数量 \033[0m" % len(failedImages)) 141 | for imageStr in failedImages: 142 | print("\033[1;31;40m %s \033[0m" % imageStr) 143 | 144 | 145 | if __name__ == '__main__': 146 | # 获取入参 147 | tinifyKey, fromFilePath, toFilePath = getInputParm(); 148 | # 检测当前将要压缩的文件下文件基本情况 149 | map = FindAllImages.checkFile(fromFilePath) 150 | 151 | print("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ") 152 | # 询问是否将要继续压缩 153 | inputStr = input("待压缩文件已检测完毕,是否继续下一步压缩操作(1/0):") 154 | if str(inputStr) != '1': 155 | exit(1) 156 | print("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ") 157 | # 开始压缩 158 | pngSum, jpgSum, toFileSize, fileSum, failedImages = compress(tinifyKey, fromFilePath, toFilePath, map["allFileSum"]) 159 | printOperateResult(map["pngSum"], pngSum, map["jpgSum"], jpgSum, map["fileSize"], toFileSize, map["allFileSum"], 160 | fileSum, failedImages) 161 | -------------------------------------------------------------------------------- /FindAllAPartFiles.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 查找某一类的文件 3 | 4 | import os 5 | import os.path 6 | import sys 7 | import getopt 8 | 9 | 10 | # 获取入参参数 11 | def getInputParm(): 12 | opts, args = getopt.getopt(sys.argv[1:], '-f:-p:-e:', ['findTypes=', 'path=', 'exceptPathNames=']) 13 | 14 | # 入参判断 15 | for opt_name, opt_value in opts: 16 | if opt_name in ('-f', '--findTypes'): 17 | # 查找文件类型 18 | findTypes = opt_value 19 | if opt_name in ('-p', '--path'): 20 | # 要检测的文件路径 21 | path = opt_value 22 | if opt_name in ('-e', '--exceptPathNames'): 23 | # 过滤的文件夹名称 24 | exceptPathNames = opt_value 25 | 26 | findTypeList = findTypes.split(",") 27 | exceptPathNameList = exceptPathNames.split(",") 28 | 29 | # for name in findTypeList: 30 | # print('name = ' + name) 31 | # 32 | # for name in exceptPathNameList: 33 | # print('exceptPathName = ' + name) 34 | # 35 | # print('path = ' + path) 36 | 37 | # 判断文件路径存不存在 38 | if not os.path.exists(path): 39 | print("\033[0;31;40m\t输入的文件路径不存在\033[0m") 40 | exit(1) 41 | 42 | return findTypeList, path, exceptPathNameList 43 | 44 | 45 | # 检查文件相关信息 46 | def checkFileInfo(findTypes, fromFilePath, exceptPathNames): 47 | fileNum = 0 48 | 49 | # 构建将要返回的数据源,这里使用Dictionary,分组返回 50 | finalData = {} 51 | for findTyte in findTypes: 52 | finalData[findTyte] = [] 53 | 54 | for root, dirs, files in os.walk(fromFilePath): 55 | 56 | # 查找是否有相同的文件名比如 .bundle 57 | for fileName in dirs: 58 | filePath = root + '/' + fileName 59 | # 检查某个数组中的文件名是否包含于路径中 60 | isContinue = checkSomeFileNamesIsInPath(exceptPathNames, filePath) 61 | if isContinue: 62 | continue 63 | 64 | for willFindName in findTypes: 65 | if willFindName in fileName: 66 | # 文件大小+文件路径拼接 67 | finalStr = getFilePathSize(filePath) + filePath 68 | finalData[willFindName].append(finalStr) 69 | fileNum = fileNum + 1 70 | break 71 | 72 | for name in files: 73 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 74 | # print("--- " + os.path.join(root, name)) 75 | # 获取文件名,扩展名 76 | fileName, fileSuffix = os.path.splitext(name) 77 | # print("=== %s" % (root + '/' + name)) 78 | # 文件的路径 79 | filePath = root + '/' + name 80 | 81 | # 检查某个数组中的文件名是否包含于路径中 82 | isContinue = checkSomeFileNamesIsInPath(exceptPathNames, filePath) 83 | # 如果上面得出的结果是需要continue的,那么continue 84 | if isContinue: 85 | continue 86 | 87 | if fileSuffix in findTypes: 88 | # 找到相关的文件,进行统计 89 | filePath = root + '/' + name 90 | fileSize = os.path.getsize(filePath) 91 | 92 | finalStr = ("%dB*" % (fileSize)) + filePath 93 | finalData[fileSuffix].append(finalStr) 94 | fileNum = fileNum + 1 95 | 96 | return finalData 97 | 98 | 99 | # 检查某个数组中的文件名是否包含于路径中 100 | def checkSomeFileNamesIsInPath(exceptPathNames, filePath): 101 | # 判断查找的文件是否在将要过滤的文件中 102 | for exceptPathName in exceptPathNames: 103 | if exceptPathName + '/' in filePath: 104 | return True 105 | break 106 | return False 107 | 108 | 109 | # 获取文件夹存储内容大小 110 | def getFilePathSize(filePathStr): 111 | fileSize = 0 112 | for root, dirs, files in os.walk(filePathStr): 113 | # 防止有的文件找不到 114 | try: 115 | for name in files: 116 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 117 | # 文件的路径 118 | filePath = root + '/' + name 119 | # 统计文件大小 120 | fileSize = fileSize + os.path.getsize(filePath) 121 | except IOError: 122 | print("") 123 | 124 | 125 | return ("%dB*" % (fileSize)) 126 | 127 | 128 | def bubbleSort(arr): 129 | for i in range(1, len(arr)): 130 | 131 | for j in range(0, len(arr) - i): 132 | 133 | findFilePathJ1 = arr[j] 134 | fileSizeIJ1 = int(findFilePathJ1.split("B*")[0]) 135 | 136 | findFilePathJ2 = arr[j + 1] 137 | fileSizeJ2 = int(findFilePathJ2.split("B*")[0]) 138 | 139 | if fileSizeIJ1 > fileSizeJ2: 140 | tempStr = arr[j] 141 | arr[j] = arr[j + 1] 142 | arr[j + 1] = tempStr 143 | return arr 144 | 145 | 146 | def transformUnit(sizeStr): 147 | size = int(sizeStr) 148 | unit = "B" 149 | if (size > 1000): 150 | size = size / 1000 151 | unit = "KB" 152 | if size > 1000: 153 | size = size / 1000; 154 | unit = "M" 155 | 156 | return ('%d%s' % (size, unit)) 157 | 158 | 159 | if __name__ == '__main__': 160 | # 获取输入的参数 161 | findTypes, path, exceptPathNames = getInputParm() 162 | finalData = checkFileInfo(findTypes, path, exceptPathNames) 163 | 164 | print("\n\n当前路径 " + path + " 中,排除 " + ', '.join(exceptPathNames) + "\n找到文件 " + ', '.join( 165 | findTypes)) 166 | 167 | for findType in findTypes: 168 | list = finalData[findType] 169 | print("\n\n发现 %s %d个" % (findType, len(list))) 170 | list = bubbleSort(list) 171 | index = 1 172 | for findFilePath in list: 173 | # 对文件的大小进行加工 174 | strList = findFilePath.split("B*") 175 | sizeStr = transformUnit(strList[0]) 176 | print("%d - %s %s" % (index, sizeStr, strList[1])) 177 | index = index + 1 178 | -------------------------------------------------------------------------------- /FindAllImages.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import os 4 | import os.path 5 | import shutil 6 | import sys 7 | import getopt 8 | 9 | # 文件检测,白名单过滤。不在白名单目录中的文件路径将会被输出,被视为异常扩展名的文件 10 | whiteSuffixList = ['.json'] 11 | # 文件名白名单 12 | whiteFileNameList = ['.DS_Store'] 13 | 14 | 15 | # 获取入参参数 16 | def getInputParm(): 17 | opts, args = getopt.getopt(sys.argv[1:], '-f:', ['filePath=']) 18 | # 入参判断 19 | for opt_name, opt_value in opts: 20 | if opt_name in ('-f', '--filePath'): 21 | return opt_value 22 | else: 23 | print("\033[0;31;40m 请按照格式输入: python/python3 " + sys.argv[0] + " -f \033[0m") 24 | exit(1) 25 | 26 | 27 | # 检查文件相关信息 28 | def checkFileInfo(fromFilePath): 29 | pngSum = 0 30 | jpgSum = 0 31 | unusualSum = 0 32 | allFileSum = 0 33 | fileSize = 0 34 | jpgArray = [] 35 | # 异常文件 36 | abnormalArray = [] 37 | 38 | for root, dirs, files in os.walk(fromFilePath): 39 | for name in files: 40 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 41 | # print("--- " + os.path.join(root, name)) 42 | # 获取文件名,扩展名 43 | fileName, fileSuffix = os.path.splitext(name) 44 | 45 | # 文件大小 46 | fileSize = fileSize + os.path.getsize(root + '/' + name) 47 | # 所有文件的数量 48 | allFileSum = allFileSum + 1 49 | # 如果扩展名是 png 或者是 jpg 的 再去压缩,其他的不管 50 | if fileSuffix == '.png': 51 | pngSum = pngSum + 1 52 | elif fileSuffix == '.jpg': 53 | jpgSum = jpgSum + 1 54 | jpgArray.append((root + '/' + name)) 55 | # print("jpg图片路径: %s" % (root + '/' + name)) 56 | else: 57 | # 非 png 和 jpg的文件 58 | if not (name in whiteFileNameList) and not (fileSuffix in whiteSuffixList): 59 | # 打印出当前是否有异常的文件 60 | unusualSum = unusualSum + 1 61 | abnormalArray.append((root + '/' + name)) 62 | 63 | print("检测到png图片:%d 张" % pngSum) 64 | print("检测到jpg图片:%d 张" % jpgSum) 65 | print("合计图片:%d 张" % (pngSum + jpgSum)) 66 | print("所有文件数:%d 个" % allFileSum) 67 | 68 | return {"pngSum": pngSum, "jpgSum": jpgSum, "unusualSum": unusualSum, "allFileSum": allFileSum, 69 | "fileSize": fileSize, "jpgArray": jpgArray, 70 | "abnormalArray": abnormalArray} 71 | 72 | 73 | # 打印相关信息 74 | def printFileInfo(fileSize, jpgArray, abnormalArray): 75 | # 文件大小 76 | unit = 'KB' 77 | fileSize = fileSize / float(1000) 78 | if fileSize > 1000: 79 | fileSize = fileSize / float(1000) 80 | unit = 'M' 81 | print("当前文件大小:%.2f %s\n" % (fileSize, unit)) 82 | if len(jpgArray) > 0: 83 | for filePath in jpgArray: 84 | print(filePath) 85 | print("\033[0;31;40m 建议将检测到的【%d】张jpg图片转化成png图片,因为打包的时候jpg会自动转化成png图片,导致包变大\n \033[0m" % len(jpgArray)) 86 | if len(abnormalArray) > 0: 87 | for filePath in abnormalArray: 88 | print(filePath) 89 | print("\033[0;31;40m 发现异常文件类型【%d】个\n \033[0m" % len(abnormalArray)) 90 | 91 | 92 | def checkFile(fromFilePath): 93 | # 检测当前路径下文件的信息 94 | map = checkFileInfo(fromFilePath) 95 | printFileInfo(map["fileSize"], map["jpgArray"], map["abnormalArray"]) 96 | return map 97 | 98 | 99 | if __name__ == '__main__': 100 | # 获取输入的参数 101 | fromFilePath = getInputParm() 102 | # 检测当前路径下文件的信息 103 | checkFile(fromFilePath) 104 | -------------------------------------------------------------------------------- /FindUnUseDefine.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 发现项目中未使用的图片资源文件 3 | import os 4 | import os.path 5 | import sys 6 | import re 7 | import getopt 8 | 9 | exceptPathNames = [] 10 | # 获取入参参数 11 | def getInputParm(): 12 | opts, args = getopt.getopt(sys.argv[1:], '-p:-e:', ['filePath=', 'exceptPathNames=']) 13 | # 获取输入的参数 14 | for opt_name, opt_value in opts: 15 | if opt_name in ('-p', '--filePath'): 16 | filePath = opt_value 17 | if opt_name in ('-e', '--exceptPathNames'): 18 | # 过滤的文件夹名称 19 | exceptPathNames = opt_value 20 | 21 | exceptPathNameList = exceptPathNames.split(",") 22 | 23 | if not os.path.exists(filePath): 24 | print("\033[0;31;40m\t输入的文件路径不存在\033[0m") 25 | exit(1) 26 | 27 | return filePath, exceptPathNameList 28 | 29 | 30 | def findAllDefines(filePath): 31 | # 找到工程里所有的宏定义 32 | for root, dirs, files in os.walk(filePath): 33 | for name in files: 34 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 35 | # print("--- " + os.path.join(root, name)) 36 | # 获取文件名,扩展名 37 | fileName, fileSuffix = os.path.splitext(name) 38 | if fileSuffix == '.m' or fileSuffix == '.h': 39 | isFinded = findDefineAtFileLine(root + '/' + name) 40 | if isFinded: 41 | # 如果找到了立即返回 42 | return True 43 | 44 | return False 45 | 46 | 47 | def checkUnUseDefine(filePath, allDefineList): 48 | unUsedDefineList = [] 49 | index = 1 50 | resultDic = {} 51 | for defineName in allDefineList: 52 | 53 | # 设置初始值 54 | if defineName not in resultDic: 55 | resultDic[defineName] = 0 56 | 57 | # 去工程里面就去找吧 58 | num = findStrAtFilePath(filePath, defineName) 59 | # 计数累加 60 | resultDic[defineName] = resultDic[defineName] + num 61 | 62 | percent = index / len(allDefineList) 63 | sys.stdout.write("\r# 共查找到【%d 个】宏定义,已分析完【%d 个】| 当前完成进度: %.1f %%" % (len(allDefineList), index, percent * 100)) 64 | sys.stdout.flush() 65 | index = index + 1 66 | 67 | for key in resultDic: 68 | if resultDic[key] == 1: 69 | unUsedDefineList.append(key) 70 | return unUsedDefineList 71 | 72 | 73 | # 查找某个文件夹下面所有的文件中是否使用了define 74 | def findStrAtFilePath(filePath, defineName): 75 | 76 | useNnm = 0 77 | # 去工程里面就去找吧 78 | for root, dirs, files in os.walk(filePath): 79 | isFind = False 80 | for name in files: 81 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 82 | # print("--- " + os.path.join(root, name)) 83 | # 获取文件名,扩展名 84 | fileName, fileSuffix = os.path.splitext(name) 85 | 86 | if fileSuffix == '.m' or fileSuffix == '.h': 87 | tempStr = defineName 88 | filePath = root + '/' + name 89 | if checkSomeFileNamesIsInPath(exceptPathNames, filePath) : 90 | continue 91 | # 在当前文件中找到几个宏定义 92 | num = findStrAtFileLineShowNum(filePath, tempStr) 93 | useNnm = useNnm + num 94 | 95 | return useNnm 96 | 97 | 98 | # 查找文件中的#define 99 | def findDefineAtFileLine(filePath): 100 | re_define1 = re.compile('#define\s+([A-Za-z0-9]+\()') 101 | re_define2 = re.compile('#define\s+([A-Za-z0-9]+)\s') 102 | define_list = [] 103 | for root, dirs, files in os.walk(filePath): 104 | isFind = False 105 | for name in files: 106 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 107 | # print("--- " + os.path.join(root, name)) 108 | # 获取文件名,扩展名 109 | fileName, fileSuffix = os.path.splitext(name) 110 | if fileSuffix == '.m' or fileSuffix == '.h': 111 | filePath = root + '/' + name 112 | if checkSomeFileNamesIsInPath(exceptPathNames, filePath) : 113 | continue 114 | file = open(filePath, 'r') 115 | for line in file: 116 | result1 = re_define1.findall(line) 117 | if result1: 118 | define_list.append(result1[0]) 119 | result2 = re_define2.findall(line) 120 | if result2: 121 | define_list.append(result2[0]) 122 | file.close() 123 | 124 | return define_list 125 | 126 | 127 | # 查找文件内容中某个字符串出现的次数 128 | def findStrAtFileLineShowNum(filePath, findStr): 129 | # global _resNameMap 130 | # 宏定义前后都不为字母或者数字 131 | rule1 = '\W('+findStr+')\W' 132 | rule2 = '^('+findStr+')\W' 133 | # 判断有木有左括号 134 | if '(' in findStr: 135 | findStr = findStr.replace('(', '') 136 | rule1 = '\W(' + findStr + '\()' 137 | rule2 = '^(' + findStr + '\()' 138 | 139 | re_define1 = re.compile(rule1) 140 | re_define2 = re.compile(rule2) 141 | file = open(filePath, 'r') 142 | result_num = 0 143 | for line in file: 144 | # print(line) 145 | # exit(1) 146 | result_list1 = re_define1.findall(line) 147 | if result_list1: 148 | result_num = result_num+len(result_list1) 149 | 150 | result_list2 = re_define2.findall(line) 151 | if result_list2: 152 | result_num = result_num + len(result_list2) 153 | 154 | file.close() 155 | 156 | return result_num 157 | 158 | # 检查某个数组中的文件名是否包含于路径中 159 | def checkSomeFileNamesIsInPath(exceptPathNames, filePath): 160 | # 判断查找的文件是否在将要过滤的文件中 161 | for exceptPathName in exceptPathNames: 162 | if exceptPathName + '/' in filePath: 163 | return True 164 | break 165 | return False 166 | 167 | 168 | if __name__ == '__main__': 169 | # 获取入参 170 | filePath, exceptPathNames = getInputParm() 171 | define_list = findDefineAtFileLine(filePath) 172 | 173 | # 开始搞事情 174 | unUsedDefineList = checkUnUseDefine(filePath, define_list) 175 | 176 | print("\n\n共扫描项目中#define【%d个】 " % (len(define_list))) 177 | print("\033[0;31;40m 扫描出【%d个】未使用 #define,请在项目中再次验证 \033[0m" % len(unUsedDefineList)) 178 | 179 | index = 1 180 | for unUseDefine in unUsedDefineList: 181 | print("【%d】 - %s" % (index,unUseDefine)) 182 | index = index + 1 183 | -------------------------------------------------------------------------------- /FindUnUseImage.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 发现项目中未使用的图片资源文件 3 | import os 4 | import os.path 5 | import sys 6 | import getopt 7 | import FindAllAPartFiles 8 | 9 | findImageTypes = ['.png', '.jpg', '.jpeg'] 10 | exceptPathNames = ['.bundle', 'Assets.xcassets', 'Pods'] 11 | 12 | 13 | # 获取入参参数 14 | def getInputParm(): 15 | opts, args = getopt.getopt(sys.argv[1:], '-p:-t:', ['fromFilePath=']) 16 | # 获取输入的参数 17 | for opt_name, opt_value in opts: 18 | if opt_name in ('-p', '--fromFilePath'): 19 | fromFilePath = opt_value 20 | 21 | if not os.path.exists(fromFilePath): 22 | print("\033[0;31;40m\t输入的压缩文件路径不存在\033[0m") 23 | exit(1) 24 | 25 | return fromFilePath 26 | 27 | 28 | def findAllImages(fromFilePath): 29 | allImageNameList = [] 30 | allImageFilePathList = [] 31 | 32 | # 获取项目中,除了bundle和Assets.xcassets下面的图片 33 | # findImageTypes = ['.png', '.jpg', '.jpeg'] 34 | # exceptPathNames = ['.bundle', 'Assets.xcassets', 'Pods'] 35 | finalData = FindAllAPartFiles.checkFileInfo(findImageTypes, fromFilePath, exceptPathNames) 36 | 37 | # 处理数据源,将找到的图片名字存储起来 38 | for findType in findImageTypes: 39 | list = finalData[findType] 40 | for filePath in list: 41 | # filepath:文件路径,不包含文件名 tmpFileName:文件名,包含后缀名 42 | filepath, tmpFileName = os.path.split(filePath) 43 | # shotName:文件名,不包含扩展名. extension:文件扩展名 44 | shotName, extension = os.path.splitext(tmpFileName) 45 | shotName = shotName.split("@")[0] 46 | allImageNameList.append(shotName) 47 | allImageFilePathList.append(filePath) 48 | 49 | for root, dirs, files in os.walk(fromFilePath): 50 | 51 | # 检测 Assets.xcassets 下的图片 52 | for fileName in dirs: 53 | if '.imageset' in fileName: 54 | shotName, extension = os.path.splitext(fileName) 55 | allImageNameList.append(shotName) 56 | allImageFilePathList.append(root + '/' + fileName) 57 | 58 | return allImageNameList, allImageFilePathList 59 | 60 | 61 | def checkUnUseImage(fromFilePath, allImageNameList, allImageFilePathList): 62 | unUsedImageList = [] 63 | index = 1 64 | for imageName in allImageNameList: 65 | # 去工程里面就去找吧 66 | isFinded = findStrAtFilePath(fromFilePath, imageName) 67 | if not isFinded: 68 | # 没有找到 69 | unUsedImageList.append(imageName) 70 | 71 | percent = index / len(allImageNameList) 72 | sys.stdout.write("\r# 共【%d 张】已分析完【%d 张】| 当前完成进度: %.1f %%" % (len(allImageNameList), index, percent * 100)) 73 | sys.stdout.flush() 74 | index = index + 1 75 | 76 | return unUsedImageList 77 | 78 | 79 | # 查找某个文件夹下面所有的文件中是否使用了image 80 | def findStrAtFilePath(fromFilePath, imageName): 81 | # 去工程里面就去找吧 82 | for root, dirs, files in os.walk(fromFilePath): 83 | isFind = False 84 | for name in files: 85 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 86 | # print("--- " + os.path.join(root, name)) 87 | # 获取文件名,扩展名 88 | fileName, fileSuffix = os.path.splitext(name) 89 | if fileSuffix == '.m' or fileSuffix == '.xib' or fileSuffix == '.storyboard' or fileSuffix == '.swift': 90 | tempStr = '\"' + imageName 91 | isFinded = findStrAtFileLine(root + '/' + name, tempStr) 92 | if isFinded: 93 | # 如果找到了立即返回 94 | return True 95 | 96 | return False 97 | 98 | 99 | # 查找文件内容是否包含某个字符串 100 | def findStrAtFileLine(filePath, findStr): 101 | # global _resNameMap 102 | file = open(filePath, 'r') 103 | isFind = False 104 | # print("findStr == " + findStr) 105 | # print("filePath == " + filePath) 106 | for line in file: 107 | # print(line) 108 | # exit(1) 109 | if findStr in line: 110 | isFind = True 111 | break 112 | file.close() 113 | return isFind 114 | 115 | 116 | if __name__ == '__main__': 117 | # 获取入参 118 | fromFilePath = getInputParm() 119 | allImageNameList, allImageFilePathList = findAllImages(fromFilePath) 120 | 121 | # 开始搞事情 122 | unUsedImageList = checkUnUseImage(fromFilePath, allImageNameList, allImageFilePathList) 123 | 124 | print("\n\n共扫描项目中图片【%s】【%d张】<不包含%s> " % (', '.join(findImageTypes), len(allImageNameList), ', '.join(exceptPathNames))) 125 | print("\033[0;31;40m 扫描出【%d张】未使用图片,请在项目中再次验证 \033[0m" % len(unUsedImageList)) 126 | 127 | index = 1 128 | for unUseImage in unUsedImageList: 129 | print("【%d】 - %s" % (index, unUseImage)) 130 | index = index + 1 131 | -------------------------------------------------------------------------------- /FindUnUseResource.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 发现项目中未使用的图片资源文件 3 | import os 4 | import os.path 5 | import sys 6 | import getopt 7 | import FindAllAPartFiles 8 | 9 | # findImageTypes = ['.png', '.jpg', '.jpeg'] 10 | # exceptPathNames = ['.bundle', 'Assets.xcassets', 'Pods'] 11 | 12 | 13 | # 获取入参参数 14 | 15 | def getInputParm(): 16 | opts, args = getopt.getopt(sys.argv[1:], '-f:-p:-e:', ['findTypes=', 'path=', 'exceptPathNames=']) 17 | 18 | # 入参判断 19 | for opt_name, opt_value in opts: 20 | if opt_name in ('-f', '--findTypes'): 21 | # 查找文件类型 22 | findTypes = opt_value 23 | if opt_name in ('-p', '--path'): 24 | # 要检测的文件路径 25 | path = opt_value 26 | if opt_name in ('-e', '--exceptPathNames'): 27 | # 过滤的文件夹名称 28 | exceptPathNames = opt_value 29 | 30 | findTypeList = findTypes.split(",") 31 | exceptPathNameList = exceptPathNames.split(",") 32 | 33 | # for name in findTypeList: 34 | # print('name = ' + name) 35 | # 36 | # for name in exceptPathNameList: 37 | # print('exceptPathName = ' + name) 38 | # 39 | # print('path = ' + path) 40 | 41 | # 判断文件路径存不存在 42 | if not os.path.exists(path): 43 | print("\033[0;31;40m\t输入的文件路径不存在\033[0m") 44 | exit(1) 45 | 46 | return findTypeList, path, exceptPathNameList 47 | 48 | 49 | 50 | def findAllImages(findTypeList, fromFilePath, exceptPathNameList): 51 | allImageNameList = [] 52 | allImageFilePathList = [] 53 | 54 | # 获取项目中,除了bundle和Assets.xcassets下面的图片 55 | # findImageTypes = ['.png', '.jpg', '.jpeg'] 56 | # exceptPathNames = ['.bundle', 'Assets.xcassets', 'Pods'] 57 | finalData = FindAllAPartFiles.checkFileInfo(findTypeList, fromFilePath, exceptPathNameList) 58 | 59 | # 处理数据源,将找到的图片名字存储起来 60 | for findType in findTypeList: 61 | list = finalData[findType] 62 | for filePath in list: 63 | # filepath:文件路径,不包含文件名 tmpFileName:文件名,包含后缀名 64 | filepath, tmpFileName = os.path.split(filePath) 65 | # shotName:文件名,不包含扩展名. extension:文件扩展名 66 | shotName, extension = os.path.splitext(tmpFileName) 67 | shotName = shotName.split("@")[0] 68 | allImageNameList.append(shotName) 69 | allImageFilePathList.append(filePath) 70 | 71 | for root, dirs, files in os.walk(fromFilePath): 72 | 73 | # 检测 Assets.xcassets 下的图片 74 | for fileName in dirs: 75 | if '.imageset' in fileName: 76 | shotName, extension = os.path.splitext(fileName) 77 | allImageNameList.append(shotName) 78 | allImageFilePathList.append(root + '/' + fileName) 79 | 80 | return allImageNameList, allImageFilePathList 81 | 82 | 83 | def checkUnUseImage(fromFilePath, allImageNameList, allImageFilePathList): 84 | unUsedImageList = [] 85 | index = 1 86 | 87 | for fileName, filePath in zip(allImageNameList, allImageFilePathList): 88 | # 去工程里面就去找吧 89 | isFinded = findStrAtFilePath(fromFilePath, fileName) 90 | if not isFinded: 91 | # 没有找到 92 | filepath, tmpfilename = os.path.split(filePath) 93 | shotname, extension = os.path.splitext(tmpfilename) 94 | name = shotname+extension 95 | unUsedImageList.append(name) 96 | 97 | percent = index / len(allImageNameList) 98 | sys.stdout.write("\r# 共【%d 个】已分析完【%d 个】| 当前完成进度: %.1f %%" % (len(allImageNameList), index, percent * 100)) 99 | sys.stdout.flush() 100 | index = index + 1 101 | 102 | return unUsedImageList 103 | 104 | 105 | # 查找某个文件夹下面所有的文件中是否使用了image 106 | def findStrAtFilePath(fromFilePath, imageName): 107 | # 去工程里面就去找吧 108 | for root, dirs, files in os.walk(fromFilePath): 109 | isFind = False 110 | for name in files: 111 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 112 | # print("--- " + os.path.join(root, name)) 113 | # 获取文件名,扩展名 114 | fileName, fileSuffix = os.path.splitext(name) 115 | if fileSuffix == '.m' or fileSuffix == '.xib' or fileSuffix == '.storyboard': 116 | tempStr = '\"' + imageName 117 | isFinded = findStrAtFileLine(root + '/' + name, tempStr) 118 | if isFinded: 119 | # 如果找到了立即返回 120 | return True 121 | 122 | return False 123 | 124 | 125 | # 查找文件内容是否包含某个字符串 126 | def findStrAtFileLine(filePath, findStr): 127 | # global _resNameMap 128 | file = open(filePath, 'r') 129 | isFind = False 130 | # print("findStr == " + findStr) 131 | # print("filePath == " + filePath) 132 | for line in file: 133 | # print(line) 134 | # exit(1) 135 | if findStr in line: 136 | isFind = True 137 | break 138 | file.close() 139 | return isFind 140 | 141 | 142 | if __name__ == '__main__': 143 | # 获取入参 144 | findTypeList, fromFilePath, exceptPathNameList = getInputParm() 145 | allImageNameList, allImageFilePathList = findAllImages(findTypeList, fromFilePath, exceptPathNameList) 146 | 147 | # 开始搞事情 148 | unUsedImageList = checkUnUseImage(fromFilePath, allImageNameList, allImageFilePathList) 149 | 150 | print("\n\n共扫描项目中资源文件【%s】【%d个】<不包含%s> " % (', '.join(findTypeList), len(allImageNameList), ', '.join(exceptPathNameList))) 151 | print("\033[0;31;40m 扫描出【%d个】未使用资源,请在项目中再次验证 \033[0m" % len(unUsedImageList)) 152 | 153 | index = 1 154 | for unUseImage in unUsedImageList: 155 | print("【%d】 - %s" % (index, unUseImage)) 156 | index = index + 1 157 | -------------------------------------------------------------------------------- /RepeatFileFindPro.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import os 4 | import os.path 5 | import sys 6 | import getopt 7 | 8 | 9 | # 获取入参参数 10 | def getInputParm(): 11 | opts, args = getopt.getopt(sys.argv[1:], '-f:-p:-e:', ['findTypes=', 'path=', 'exceptPathNames=']) 12 | 13 | # 入参判断 14 | for opt_name, opt_value in opts: 15 | if opt_name in ('-f', '--findTypes'): 16 | # 查找文件类型 17 | findTypes = opt_value 18 | if opt_name in ('-p', '--path'): 19 | # 要检测的文件路径 20 | path = opt_value 21 | if opt_name in ('-e', '--exceptPathNames'): 22 | # 过滤的文件夹名称 23 | exceptPathNames = opt_value 24 | 25 | findTypeList = findTypes.split(",") 26 | exceptPathNameList = exceptPathNames.split(",") 27 | 28 | # for name in findTypeList: 29 | # print('name = ' + name) 30 | # 31 | # for name in exceptPathNameList: 32 | # print('exceptPathName = ' + name) 33 | # 34 | # print('path = ' + path) 35 | 36 | # 判断文件路径存不存在 37 | if not os.path.exists(path): 38 | print("\033[0;31;40m\t输入的文件路径不存在\033[0m") 39 | exit(1) 40 | 41 | return findTypeList, path, exceptPathNameList 42 | 43 | 44 | # 检查文件相关信息 45 | def checkFileInfo(findTypes, fromFilePath, exceptPathNames): 46 | returnFileNames = [] 47 | returnFilePaths = [] 48 | 49 | for root, dirs, files in os.walk(fromFilePath): 50 | 51 | # 查找是否有相同的文件名比如 .bundle 52 | for fileName in dirs: 53 | filePath = root + '/' + fileName 54 | # 检查某个数组中的文件名是否包含于路径中 55 | # isContinue = checkSomeFileNamesIsInPath(exceptPathNames, filePath) 56 | # if isContinue: 57 | # continue 58 | 59 | for willFindName in findTypes: 60 | if willFindName in fileName: 61 | # 文件名称和文件路径存储 62 | returnFileNames.append(fileName) 63 | returnFilePaths.append(filePath) 64 | break 65 | 66 | for name in files: 67 | # os.path.join路径拼接 os.path.join(root, name) 直接获取最里面一层文件 68 | # print("--- " + os.path.join(root, name)) 69 | # 获取文件名,扩展名 70 | fileName, fileSuffix = os.path.splitext(name) 71 | # print("=== %s" % (root + '/' + name)) 72 | # 文件的路径 73 | filePath = root + '/' + name 74 | 75 | # 检查某个数组中的文件名是否包含于路径中 76 | isContinue = checkSomeFileNamesIsInPath(exceptPathNames, filePath) 77 | # 如果上面得出的结果是需要continue的,那么continue 78 | if isContinue: 79 | continue 80 | 81 | if fileSuffix in findTypes: 82 | # 找到相关的文件,进行统计 83 | filePath = root + '/' + name 84 | returnFileNames.append(name) 85 | returnFilePaths.append(filePath) 86 | 87 | return returnFileNames, returnFilePaths 88 | 89 | 90 | # 检查某个数组中的文件名是否包含于路径中 91 | def checkSomeFileNamesIsInPath(exceptPathNames, filePath): 92 | # 判断查找的文件是否在将要过滤的文件中 93 | for exceptPathName in exceptPathNames: 94 | if exceptPathName + '/' in filePath: 95 | return True 96 | break 97 | return False 98 | 99 | 100 | if __name__ == '__main__': 101 | # 获取输入的参数 102 | findTypes, fromFilePath, exceptPathNames = getInputParm() 103 | returnFileNames, returnFilePaths = checkFileInfo(findTypes, fromFilePath, exceptPathNames) 104 | 105 | # 文件个数 106 | fileNumDic = {} 107 | # 文件路径 108 | filePathDic = {} 109 | for fileName, filePath in zip(returnFileNames, returnFilePaths): 110 | 111 | # 使用字典统计重复名字 112 | fileNum = 0 113 | filePaths = [] 114 | if fileName in fileNumDic: 115 | fileNum = fileNumDic[fileName] 116 | filePaths = filePathDic[fileName] 117 | 118 | fileNum = fileNum + 1 119 | fileNumDic[fileName] = fileNum 120 | 121 | filePaths.append(filePath) 122 | filePathDic[fileName] = filePaths 123 | 124 | # 重复文件数量 125 | num = 0 126 | # 遍历map中文件数量大于2的,打印出来 127 | for fileName in fileNumDic: 128 | fileNum = fileNumDic[fileName] 129 | if fileNum > 1: 130 | print("\n 重复文件【%s】 重复数量-- 【%s个】" % (fileName, fileNum)) 131 | filePaths = filePathDic[fileName] 132 | 133 | for filePath in filePaths: 134 | print(filePath) 135 | num = num + 1 136 | 137 | resultStr = "\n\n在路径 " + fromFilePath + " 中,排除文件夹类型【" + ', '.join(exceptPathNames) + "】 \n找到【" + ', '.join( 138 | findTypes) + "】类型的重复文件【%d】个" % num 139 | print("\033[0;31;40m %s \033[0m" % resultStr) 140 | -------------------------------------------------------------------------------- /__pycache__/FindAllAPartFiles.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yan998/TinyImages/31ac83b10b7c9f52d39f96a1f43bc297b77cf532/__pycache__/FindAllAPartFiles.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/FindAllImages.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yan998/TinyImages/31ac83b10b7c9f52d39f96a1f43bc297b77cf532/__pycache__/FindAllImages.cpython-37.pyc --------------------------------------------------------------------------------