Python根据文件后缀统计文件巨细、找出文件位置(仿Everything)

[复制链接]
发表于 前天 01:42 | 显示全部楼层 |阅读模式
需求分析


这个脚本支持扫描并统计某个文件夹内,以某个后缀末端的,好比sql,java(以使用参数为准)。而且可以看到此中的文件巨细和完备文件路径,还支持以CSV、XLSX等格式导出等。这个脚本实用于统计本地代码行数之后,必要查察某个编程语言,好比Java写了多少文件、每个文件巨细是多少、文件路径在那里等操纵。
使用教程


我们使用脚本时,输入想要检测的路径、文件后缀、以及是否导出文件、导出文件的定名(文件数目过多时使用)等就好。
好比python list_zip_contents.py -tp “C:\Users\your_name\Pictures\” -a -o rpng.csv   ,演示时为best.csv。

末了,用编辑器打开即可。

详细代码
  1. # -*- coding: utf-8 -*-
  2. import zipfile
  3. import os
  4. import argparse
  5. EXTENSIONS = {
  6.     'sql': '.sql', 'java': '.java', 'c': '.c', 'cpp': '.cpp', 'h': '.h',
  7.     'py': '.py', 'js': '.js', 'html': '.html', 'css': '.css', 'markdown': '.md',
  8.     'txt': '.txt', 'xml': '.xml', 'yaml': '.yaml', 'yml': '.yml', 'json': '.json',
  9.     'properties': '.properties', 'go': '.go', 'rs': '.rs', 'rb': '.rb',
  10.     'php': '.php', 'swift': '.swift', 'kt': '.kt', 'cs': '.cs', 'lua': '.lua',
  11.     'sh': '.sh', 'bat': '.bat', 'ps1': '.ps1', 'sql': '.sql'
  12. }
  13. def split_archive_path(path):
  14.     lower_path = path.lower()
  15.     all_extensions = ['.tar.gz', '.tar.bz2', '.tar.zst', '.tgz', '.zip', '.7z', '.rar', '.tar', '.gz', '.bz2']
  16.     candidates = []
  17.     for ext in all_extensions:
  18.         ext_lower = ext.lower()
  19.         idx = lower_path.rfind(ext_lower)
  20.         if idx >= 0:
  21.             candidates.append((idx, len(ext), ext, path[:idx + len(ext)], path[idx + len(ext):].lstrip('\\').lstrip('/')))
  22.     if candidates:
  23.         candidates.sort(key=lambda x: (x[0], -x[1]))
  24.         _, _, _, archive_path, sub_path = candidates[0]
  25.         if sub_path:
  26.             return archive_path, sub_path
  27.         else:
  28.             return archive_path, ''
  29.     return path, ''
  30. def is_archive(path):
  31.     return path.lower().endswith(('.zip', '.7z', '.rar', '.tar', '.tar.gz', '.tar.bz2', '.tgz', '.gz', '.bz2'))
  32. def list_files_in_path(target_path, filter_exts, show_all):
  33.     if os.path.isdir(target_path):
  34.         return list_files_in_dir(target_path, filter_exts, show_all)
  35.     elif os.path.isfile(target_path) and is_archive(target_path):
  36.         return list_files_in_archive(target_path, filter_exts, show_all)
  37.     else:
  38.         archive_path, sub_path = split_archive_path(target_path)
  39.         if os.path.isfile(archive_path) and is_archive(archive_path) and sub_path:
  40.             return list_files_in_archive_subdir(archive_path, sub_path, filter_exts, show_all)
  41.         else:
  42.             return {'error': f'Not a valid directory or zip file - {target_path}', 'files': [], 'header': ''}
  43. def list_files_in_archive_subdir(zip_path, sub_path, filter_exts, show_all):
  44.     import tempfile
  45.     temp_dir = tempfile.mkdtemp()
  46.     try:
  47.         if zip_path.lower().endswith('.zip'):
  48.             with zipfile.ZipFile(zip_path, 'r') as z:
  49.                 for member in z.namelist():
  50.                     normalized = member.replace('/', os.sep).replace('\\', os.sep)
  51.                     sub_path_normalized = sub_path.replace('/', os.sep).replace('\\', os.sep)
  52.                     if normalized.startswith(sub_path_normalized + os.sep) or normalized == sub_path_normalized:
  53.                         z.extract(member, temp_dir)
  54.         elif zip_path.lower().endswith('.7z'):
  55.             import py7zr
  56.             with py7zr.SevenZipFile(zip_path, 'r') as sz:
  57.                 sz.extractall(temp_dir)
  58.         else:
  59.             return {'error': f'Unsupported archive format - {zip_path}', 'files': [], 'header': ''}
  60.         extract_subdir = temp_dir
  61.         for item in os.listdir(temp_dir):
  62.             if sub_path.replace('/', os.sep).replace('\\', os.sep).endswith(item) or item.endswith('.zip') or item.endswith('.7z'):
  63.                 potential = os.path.join(temp_dir, item)
  64.                 if os.path.isdir(potential):
  65.                     extract_subdir = potential
  66.                     break
  67.         return list_files_recursive(extract_subdir, filter_exts, show_all, zip_path, sub_path)
  68.     finally:
  69.         import shutil
  70.         try:
  71.             shutil.rmtree(temp_dir)
  72.         except:
  73.             pass
  74. def list_files_recursive(dir_path, filter_exts, show_all, archive_path=None, sub_path=None):
  75.     files_found = []
  76.     dirs_to_scan = [dir_path]
  77.     while dirs_to_scan:
  78.         current_dir = dirs_to_scan.pop()
  79.         for root, dirs, files in os.walk(current_dir):
  80.             for filename in files:
  81.                 filepath = os.path.join(root, filename)
  82.                 try:
  83.                     size = os.path.getsize(filepath)
  84.                 except:
  85.                     size = 0
  86.                 rel_path = os.path.relpath(filepath, dir_path)
  87.                 ext = filename.lower()
  88.                 if ext.endswith(('.zip', '.7z', '.rar', '.tar', '.tar.gz', '.tgz', '.gz', '.bz2')):
  89.                     nested_result = try_extract_nested(filepath, filter_exts, show_all)
  90.                     if nested_result:
  91.                         files_found.extend(nested_result['files'])
  92.                     continue
  93.                 if show_all:
  94.                     files_found.append((rel_path, size))
  95.                 else:
  96.                     file_ext = os.path.splitext(filename)[1].lower()
  97.                     if file_ext in filter_exts:
  98.                         files_found.append((rel_path, size))
  99.     if archive_path and sub_path:
  100.         header = f'Archive: {archive_path} / {sub_path}'
  101.     elif archive_path:
  102.         header = f'Archive: {archive_path}'
  103.     else:
  104.         header = f'Directory: {dir_path}'
  105.     header += f'\nTotal files: {len(files_found)}\n' + '=' * 80
  106.     return {'files': sorted(files_found), 'header': header}
  107. def try_extract_nested(archive_file, filter_exts, show_all):
  108.     import tempfile
  109.     temp_dir = tempfile.mkdtemp()
  110.     try:
  111.         ext = archive_file.lower()
  112.         if ext.endswith('.zip'):
  113.             with zipfile.ZipFile(archive_file, 'r') as z:
  114.                 z.extractall(temp_dir)
  115.         elif ext.endswith('.7z'):
  116.             import py7zr
  117.             with py7zr.SevenZipFile(archive_file, 'r') as sz:
  118.                 sz.extractall(temp_dir)
  119.         else:
  120.             return None
  121.         files_found = []
  122.         for root, dirs, files in os.walk(temp_dir):
  123.             for filename in files:
  124.                 filepath = os.path.join(root, filename)
  125.                 try:
  126.                     size = os.path.getsize(filepath)
  127.                 except:
  128.                     size = 0
  129.                 rel_path = os.path.relpath(filepath, temp_dir)
  130.                 if show_all:
  131.                     files_found.append((rel_path, size))
  132.                 else:
  133.                     file_ext = os.path.splitext(filename)[1].lower()
  134.                     if file_ext in filter_exts:
  135.                         files_found.append((rel_path, size))
  136.         return {'files': sorted(files_found), 'header': f'Nested: {archive_file}'}
  137.     except:
  138.         return None
  139.     finally:
  140.         import shutil
  141.         try:
  142.             shutil.rmtree(temp_dir)
  143.         except:
  144.             pass
  145. def list_files_in_archive(zip_path, filter_exts, show_all):
  146.     if zip_path.lower().endswith('.zip'):
  147.         return list_files_in_zip(zip_path, filter_exts, show_all)
  148.     elif zip_path.lower().endswith('.7z'):
  149.         return list_files_in_7z(zip_path, filter_exts, show_all)
  150.     else:
  151.         return {'error': f'Unsupported archive format - {zip_path}', 'files': [], 'header': ''}
  152. def list_files_in_7z(archive_path, filter_exts, show_all):
  153.     import py7zr
  154.     import tempfile
  155.     temp_dir = tempfile.mkdtemp()
  156.     try:
  157.         with py7zr.SevenZipFile(archive_path, 'r') as sz:
  158.             sz.extractall(temp_dir)
  159.         files_found = []
  160.         for root, dirs, files in os.walk(temp_dir):
  161.             for filename in files:
  162.                 filepath = os.path.join(root, filename)
  163.                 try:
  164.                     size = os.path.getsize(filepath)
  165.                 except:
  166.                     size = 0
  167.                 rel_path = os.path.relpath(filepath, temp_dir)
  168.                 if show_all:
  169.                     files_found.append((rel_path, size))
  170.                 else:
  171.                     ext = os.path.splitext(filename)[1].lower()
  172.                     if ext in filter_exts:
  173.                         files_found.append((rel_path, size))
  174.         return {'files': sorted(files_found), 'header': f'Archive: {archive_path}\nTotal files: {len(files_found)}\n' + '=' * 80}
  175.     finally:
  176.         import shutil
  177.         try:
  178.             shutil.rmtree(temp_dir)
  179.         except:
  180.             pass
  181. def list_files_in_zip_subdir(zip_path, sub_path, filter_exts, show_all):
  182.     import tempfile
  183.     temp_dir = tempfile.mkdtemp()
  184.     try:
  185.         with zipfile.ZipFile(zip_path, 'r') as z:
  186.             for member in z.namelist():
  187.                 if member.startswith(sub_path + '/') or member == sub_path:
  188.                     z.extract(member, temp_dir)
  189.         extract_subdir = os.path.join(temp_dir, sub_path)
  190.         if os.path.exists(extract_subdir):
  191.             files_found = []
  192.             for root, dirs, files in os.walk(extract_subdir):
  193.                 for filename in files:
  194.                     filepath = os.path.join(root, filename)
  195.                     try:
  196.                         size = os.path.getsize(filepath)
  197.                     except:
  198.                         size = 0
  199.                     rel_path = os.path.relpath(filepath, extract_subdir)
  200.                     if show_all:
  201.                         files_found.append((rel_path, size))
  202.                     else:
  203.                         ext = os.path.splitext(filename)[1].lower()
  204.                         if ext in filter_exts:
  205.                             files_found.append((rel_path, size))
  206.             print(f'Archive: {zip_path} / {sub_path}')
  207.             print(f'Total files: {len(files_found)}')
  208.             print('=' * 80)
  209.             for path, size in sorted(files_found):
  210.                 print(f'{size:>12,} bytes  {path}')
  211.         else:
  212.             print(f'Error: Subdirectory not found in archive - {sub_path}')
  213.     finally:
  214.         import shutil
  215.         try:
  216.             shutil.rmtree(temp_dir)
  217.         except:
  218.             pass
  219. def list_files_in_dir(dir_path, filter_exts, show_all):
  220.     files_found = []
  221.     for root, dirs, files in os.walk(dir_path):
  222.         for filename in files:
  223.             filepath = os.path.join(root, filename)
  224.             try:
  225.                 size = os.path.getsize(filepath)
  226.             except:
  227.                 size = 0
  228.             rel_path = os.path.relpath(filepath, dir_path)
  229.             if show_all:
  230.                 files_found.append((rel_path, size))
  231.             else:
  232.                 ext = os.path.splitext(filename)[1].lower()
  233.                 if ext in filter_exts:
  234.                     files_found.append((rel_path, size))
  235.     return {'files': sorted(files_found), 'header': f'Directory: {dir_path}\nTotal files: {len(files_found)}\n' + '=' * 80}
  236. def list_files_in_zip(zip_path, filter_exts, show_all):
  237.     if not os.path.exists(zip_path):
  238.         return {'error': f'File not found - {zip_path}', 'files': [], 'header': ''}
  239.     with zipfile.ZipFile(zip_path, 'r') as z:
  240.         files_found = []
  241.         for name in z.namelist():
  242.             info = z.getinfo(name)
  243.             if info.file_size == 0:
  244.                 continue
  245.             if show_all:
  246.                 files_found.append((name, info.file_size))
  247.             else:
  248.                 ext = os.path.splitext(name)[1].lower()
  249.                 if ext in filter_exts:
  250.                     files_found.append((name, info.file_size))
  251.         return {'files': sorted(files_found), 'header': f'Archive: {zip_path}\nTotal files: {len(files_found)}\n' + '=' * 80}
  252. def main():
  253.     import sys
  254.    
  255.     parser = argparse.ArgumentParser(
  256.         description='List files in a zip archive with filtering by type',
  257.         formatter_class=argparse.RawDescriptionHelpFormatter,
  258.         epilog='''
  259. Examples:
  260.   python list_zip_contents.py --target_path archive.zip --all
  261.   python list_zip_contents.py --target_path archive.zip --type java py js
  262.   python list_zip_contents.py --target_path archive.zip --type sql
  263.   python list_zip_contents.py archive.zip --type c cpp h
  264.         '''
  265.     )
  266.     parser.add_argument('positional_path', nargs='?', help='Path to the zip archive')
  267.     parser.add_argument('-tp', '--target_path', '--target', dest='target_path', help='Path to the zip archive')
  268.     parser.add_argument('-t', '--type', '--types', dest='types', nargs='+',
  269.                         help=f'File types to filter: {" ".join(EXTENSIONS.keys())}')
  270.     parser.add_argument('-a', '--all', dest='show_all', action='store_true',
  271.                         help='Show all files instead of code files only')
  272.     parser.add_argument('-o', '--output', '--out', dest='output',
  273.                         help='Output file path (e.g., result.csv, result.xlsx)')
  274.     args = parser.parse_args()
  275.     if args.target_path:
  276.         zip_path = args.target_path
  277.     elif args.positional_path:
  278.         zip_path = args.positional_path
  279.     else:
  280.         parser.print_help()
  281.         return
  282.     run_dir = os.getcwd()
  283.     script_dir = os.path.dirname(os.path.abspath(__file__))
  284.     output_dir = run_dir if os.path.exists(run_dir) else script_dir
  285.    
  286.     types = args.types if args.types else list(EXTENSIONS.keys())
  287.     filter_exts = set(EXTENSIONS.values())
  288.     if args.types:
  289.         filter_exts = {EXTENSIONS.get(t, '.' + t) for t in args.types}
  290.     result = list_files_in_path(zip_path, filter_exts, args.show_all)
  291.     if result.get('error'):
  292.         print(result['error'])
  293.         return
  294.     if args.output:
  295.         output_path = args.output
  296.         ext = os.path.splitext(output_path)[1].lower()
  297.         
  298.         target_name = os.path.basename(zip_path)
  299.         target_stem = os.path.splitext(target_name)[0]
  300.         
  301.         if not os.path.isabs(output_path):
  302.             output_path = os.path.join(output_dir, output_path)
  303.     filter_exts = set(EXTENSIONS.values())
  304.     if args.types:
  305.         filter_exts = {EXTENSIONS.get(t, '.' + t) for t in args.types}
  306.     result = list_files_in_path(zip_path, filter_exts, args.show_all)
  307.     if result.get('error'):
  308.         print(result['error'])
  309.         return
  310.     if args.output:
  311.         output_path = args.output
  312.         ext = os.path.splitext(output_path)[1].lower()
  313.         
  314.         target_name = os.path.basename(zip_path)
  315.         target_stem = os.path.splitext(target_name)[0]
  316.         
  317.         if not os.path.isabs(output_path):
  318.             output_path = os.path.join(output_dir, output_path)
  319.         
  320.         if os.path.exists(output_path):
  321.             print(f'File "{output_path}" already exists. Overwrite? (Yes/No): ')
  322.             choice = input().strip().lower()
  323.             if choice != 'yes' and choice != 'y':
  324.                 default_name = f'{target_stem}_{ext[1:]}' if ext else target_stem
  325.                 print(f'Please modify the file name to: {default_name}')
  326.                 new_name = input().strip()
  327.                 if new_name:
  328.                     if not os.path.isabs(new_name):
  329.                         new_name = os.path.join(output_dir, new_name)
  330.                     output_path = new_name
  331.                 else:
  332.                     output_path = os.path.join(output_dir, default_name)
  333.         
  334.         abs_path = os.path.abspath(output_path)
  335.         if ext == '.csv':
  336.             import csv
  337.             with open(output_path, 'w', newline='', encoding='utf-8') as f:
  338.                 writer = csv.writer(f, lineterminator='\n')
  339.                 writer.writerow(['Size (bytes)', 'Path'])
  340.                 for path, size in result['files']:
  341.                     writer.writerow([size, path])
  342.             print(f'CSV saved to: {abs_path}')
  343.         elif ext in ('.xlsx', '.xls'):
  344.             from openpyxl import Workbook
  345.             wb = Workbook()
  346.             ws = wb.active
  347.             ws.title = 'Files'
  348.             ws.append(['Size (bytes)', 'Path'])
  349.             for path, size in result['files']:
  350.                 ws.append([size, path])
  351.             for col in ws.columns:
  352.                 max_length = 0
  353.                 col_letter = col[0].column_letter
  354.                 for cell in col:
  355.                     if cell.value:
  356.                         max_length = max(max_length, len(str(cell.value)))
  357.                 ws.column_dimensions[col_letter].width = min(max_length + 2, 80)
  358.             wb.save(output_path)
  359.             print(f'Excel saved: {abs_path}')
  360.         else:
  361.             print(f'Error: Unsupported file extension - {ext}')
  362.             return
  363.     else:
  364.         if result['header']:
  365.             print(result['header'])
  366.         for path, size in result['files']:
  367.             print(f'{size:>12,} bytes  {path}')
  368. if __name__ == '__main__':
  369.     main()
复制代码
优化发起

仅支持csv、xlsx,发起添加md格式,大概结及格式转换等在线网站。
仅支持后缀,发起添加正则匹配,可以向everything那样支持恣意关键字搜刮。
埋伏影响,不支持exe格式等文件格式扫描,大概会被防火墙EDR等产物或服务制止。

免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表