83 lines
2.8 KiB
Python
83 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Directory analyzer: counts files, sizes, and types."""
|
|
import os
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
from collections import Counter
|
|
|
|
def analyze_dir(path: str) -> dict:
|
|
"""Analyze a directory and return statistics."""
|
|
p = Path(path)
|
|
if not p.exists():
|
|
return {"error": f"Path does not exist: {path}"}
|
|
|
|
stats = {
|
|
"path": str(p.resolve()),
|
|
"total_files": 0,
|
|
"total_dirs": 0,
|
|
"total_size_bytes": 0,
|
|
"file_extensions": Counter(),
|
|
"largest_file": {"path": None, "size": 0},
|
|
"smallest_file": {"path": None, "size": float('inf')},
|
|
}
|
|
|
|
for item in p.rglob('*'):
|
|
if item.is_file():
|
|
stats["total_files"] += 1
|
|
size = item.stat().st_size
|
|
stats["total_size_bytes"] += size
|
|
|
|
ext = item.suffix.lower() if item.suffix else "(no extension)"
|
|
stats["file_extensions"][ext] += 1
|
|
|
|
if size > stats["largest_file"]["size"]:
|
|
stats["largest_file"] = {"path": str(item), "size": size}
|
|
if size < stats["smallest_file"]["size"]:
|
|
stats["smallest_file"] = {"path": str(item), "size": size}
|
|
elif item.is_dir():
|
|
stats["total_dirs"] += 1
|
|
|
|
if stats["smallest_file"]["path"] is None:
|
|
stats["smallest_file"] = {"path": None, "size": 0}
|
|
|
|
stats["file_extensions"] = dict(stats["file_extensions"])
|
|
stats["total_size_human"] = f"{stats['total_size_bytes'] / 1024:.2f} KB"
|
|
|
|
return stats
|
|
|
|
def summary_report(path: str) -> str:
|
|
"""Generate a human-readable summary."""
|
|
result = analyze_dir(path)
|
|
if "error" in result:
|
|
return f"Error: {result['error']}"
|
|
|
|
lines = [
|
|
f"Directory: {result['path']}",
|
|
f"Total files: {result['total_files']}",
|
|
f"Total directories: {result['total_dirs']}",
|
|
f"Total size: {result['total_size_human']} ({result['total_size_bytes']:,} bytes)",
|
|
"",
|
|
"Top 5 extensions by count:",
|
|
]
|
|
|
|
sorted_exts = sorted(result['file_extensions'].items(), key=lambda x: -x[1])[:5]
|
|
for ext, count in sorted_exts:
|
|
lines.append(f" {ext or '(none)'}: {count}")
|
|
|
|
lines.append("")
|
|
lines.append(f"Largest file: {result['largest_file']['path']}")
|
|
lines.append(f" Size: {result['largest_file']['size']:,} bytes")
|
|
lines.append("")
|
|
lines.append(f"Smallest file: {result['smallest_file']['path']}")
|
|
lines.append(f" Size: {result['smallest_file']['size']} bytes")
|
|
|
|
return "\n".join(lines)
|
|
|
|
if __name__ == "__main__":
|
|
target = sys.argv[1] if len(sys.argv) > 1 else "/etc"
|
|
if "--json" in sys.argv:
|
|
result = analyze_dir(target)
|
|
print(json.dumps(result, indent=2))
|
|
else:
|
|
print(summary_report(target)) |