You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

130 lines
4.3 KiB

#!/usr/bin/env python3
"""
Example: List files in an MPQ archive with detailed information
"""
from pystorm import MPQArchive
from pathlib import Path
import sys
def format_size(size_bytes):
"""Format size in bytes to human-readable format"""
for unit in ['B', 'KB', 'MB', 'GB']:
if size_bytes < 1024.0:
return f"{size_bytes:.2f} {unit}"
size_bytes /= 1024.0
return f"{size_bytes:.2f} TB"
def list_archive_files(archive_path, pattern="*", detailed=False):
"""
List files in an MPQ archive
Args:
archive_path: Path to the MPQ archive
pattern: Pattern to match files (default: "*")
detailed: Show detailed information (default: False)
"""
archive_path = Path(archive_path)
if not archive_path.exists():
print(f"Error: Archive not found: {archive_path}")
return False
print(f"Archive: {archive_path}")
print(f"Pattern: {pattern}\n")
try:
with MPQArchive(str(archive_path)) as archive:
# Find files
files = archive.find_files(pattern)
if not files:
print("No files found matching pattern")
return True
print(f"Found {len(files)} file(s)\n")
# Calculate totals
total_size = sum(f['size'] for f in files)
total_compressed = sum(f['compressed_size'] for f in files)
if detailed:
# Detailed listing
print(f"{'Name':<50} {'Size':<12} {'Compressed':<12} {'Ratio':<8} {'Flags'}")
print("=" * 100)
for file_info in sorted(files, key=lambda x: x['name']):
name = file_info['name']
size = file_info['size']
compressed = file_info['compressed_size']
flags = file_info['flags']
# Calculate compression ratio
if size > 0:
ratio = (1 - compressed / size) * 100
else:
ratio = 0
# Format flags
flag_str = []
if flags & 0x00000200: # MPQ_FILE_COMPRESS
flag_str.append("C")
if flags & 0x00010000: # MPQ_FILE_ENCRYPTED
flag_str.append("E")
if flags & 0x01000000: # MPQ_FILE_SINGLE_UNIT
flag_str.append("S")
flag_display = "".join(flag_str) or "-"
print(f"{name:<50} {format_size(size):<12} {format_size(compressed):<12} "
f"{ratio:>6.1f}% {flag_display}")
else:
# Simple listing
for file_info in sorted(files, key=lambda x: x['name']):
print(f" {file_info['name']}")
# Print summary
print("\n" + "=" * 100)
print(f"Total files: {len(files)}")
print(f"Total size: {format_size(total_size)}")
print(f"Total compressed: {format_size(total_compressed)}")
if total_size > 0:
overall_ratio = (1 - total_compressed / total_size) * 100
print(f"Overall compression ratio: {overall_ratio:.1f}%")
return True
except Exception as e:
print(f"Error reading archive: {e}")
return False
def main():
"""Main entry point"""
if len(sys.argv) < 2:
print("Usage: python list_files.py <archive.mpq> [pattern] [--detailed]")
print("\nExample:")
print(" python list_files.py game.mpq")
print(" python list_files.py game.mpq '*.txt'")
print(" python list_files.py game.mpq '*' --detailed")
sys.exit(1)
archive_path = sys.argv[1]
pattern = "*"
detailed = False
# Parse arguments
for arg in sys.argv[2:]:
if arg == "--detailed" or arg == "-d":
detailed = True
elif not arg.startswith('-'):
pattern = arg
success = list_archive_files(archive_path, pattern, detailed)
sys.exit(0 if success else 1)
if __name__ == "__main__":
main()