97 lines
4.3 KiB
Python
97 lines
4.3 KiB
Python
import os
|
|
import argparse
|
|
import csv
|
|
from pathlib import Path
|
|
|
|
def count_lines_chars(file_path):
|
|
lines = 0
|
|
chars = 0 # 改名为chars更准确
|
|
try:
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
for line in f:
|
|
stripped_line = line.strip()
|
|
if stripped_line: # 只统计非空行
|
|
lines += 1
|
|
chars += len(stripped_line) # 直接计算行的字符长度
|
|
except (UnicodeDecodeError, PermissionError):
|
|
# 忽略二进制文件或无权限文件
|
|
return 0, 0
|
|
return lines, chars
|
|
|
|
def should_exclude(path, exclude_dirs, exclude_files):
|
|
path = Path(path).resolve()
|
|
for excluded in exclude_dirs + exclude_files:
|
|
excluded_path = Path(excluded).resolve()
|
|
try:
|
|
if path == excluded_path or excluded_path in path.parents:
|
|
return True
|
|
except (PermissionError, FileNotFoundError):
|
|
continue
|
|
return False
|
|
|
|
def scan_directory(directory, extensions, exclude_dirs, exclude_files):
|
|
results = []
|
|
file_count = 0
|
|
processed_count = 0
|
|
# 先计算总文件数用于进度显示
|
|
print("正在扫描文件...")
|
|
for root, dirs, files in os.walk(directory):
|
|
dirs[:] = [d for d in dirs if not should_exclude(os.path.join(root, d), exclude_dirs, exclude_files)]
|
|
file_count += len([f for f in files if not should_exclude(os.path.join(root, f), exclude_dirs, exclude_files)])
|
|
print(f"共发现 {file_count} 个文件,开始统计...")
|
|
for root, dirs, files in os.walk(directory):
|
|
# 修改dirs列表来排除目录(原地修改)
|
|
dirs[:] = [d for d in dirs if not should_exclude(os.path.join(root, d), exclude_dirs, exclude_files)]
|
|
for file in files:
|
|
file_path = os.path.join(root, file)
|
|
if should_exclude(file_path, exclude_dirs, exclude_files):
|
|
continue
|
|
if extensions:
|
|
ext = os.path.splitext(file)[1][1:] # 去掉点号
|
|
if ext.lower() not in [e.lower() for e in extensions]:
|
|
continue
|
|
processed_count += 1
|
|
print(f"\r处理进度: {processed_count}/{file_count} ({processed_count/file_count:.1%}) | 当前文件: {file_path}", end='', flush=True)
|
|
lines, chars = count_lines_chars(file_path)
|
|
if lines > 0: # 只统计有效的文件
|
|
results.append({
|
|
'file': file_path,
|
|
'lines': lines,
|
|
'words': chars
|
|
})
|
|
print("\n统计完成!")
|
|
return results
|
|
|
|
def save_to_csv(results, csv_file):
|
|
print(f"正在保存结果到 {csv_file}...")
|
|
with open(csv_file, 'w', newline='', encoding='utf-8') as f:
|
|
writer = csv.DictWriter(f, fieldnames=['file', 'lines', 'words'])
|
|
writer.writeheader()
|
|
writer.writerows(results)
|
|
print("保存完成!")
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='统计目录下文件的代码行数和字数')
|
|
parser.add_argument('--ext', nargs='*', help='要统计的文件扩展名列表', default=[])
|
|
parser.add_argument('--exclude-dirs', nargs='*', help='要排除的目录列表', default=[])
|
|
parser.add_argument('--csv', help='输出CSV文件路径')
|
|
#args = parser.parse_args()
|
|
class args:
|
|
csv = "lines.csv"
|
|
ext = ['py', 'c']
|
|
exclude_dirs = ".ENV build TESTWORK Termination4.build Termination4.dist Termination4.onefile-build TESTWORK/.ENV TESTWORK/Build TLUI/.TEST_ENV .inf/.ENV tools-ocr/stb".split(" ")
|
|
current_dir = os.getcwd()
|
|
results = scan_directory(current_dir, args.ext, args.exclude_dirs, [])
|
|
if args.csv:
|
|
save_to_csv(results, args.csv)
|
|
total_lines = sum(r['lines'] for r in results)
|
|
total_words = sum(r['words'] for r in results)
|
|
print(f"\n统计结果:")
|
|
print(f"文件总数: {len(results)}")
|
|
print(f"总行数: {total_lines}")
|
|
print(f"总字数: {total_words}")
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
#c:/Users/Lenovo/Desktop/Termination4/line.py --ext py c --exclude-dirs .ENV build TESTWORK Termination4.build Termination4.dist Termination4.onefile-build PyVNC/.ENV TESTWORK/.ENV TESTWORK/Build TLUI/.TEST_ENV tools-ocr/stb TBuild TLUI/ttkbootstrap --csv lines.csv
|