86 lines
2.5 KiB
Python
86 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Hermes Snippet Tool: file_search_tool.py
|
|
A quick utility to search file contents with regex patterns.
|
|
|
|
Usage: python file_search_tool.py <directory> <pattern> [output_file]
|
|
|
|
Example: python file_search_tool.py /root .env secrets /tmp/results.txt
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import re
|
|
import json
|
|
from pathlib import Path
|
|
|
|
def search_files(directory: str, pattern: str, output_file: str = None) -> dict:
|
|
"""Search for regex pattern in files within directory."""
|
|
results = {"matches": [], "count": 0, "searched": 0}
|
|
|
|
try:
|
|
regex = re.compile(pattern, re.IGNORECASE)
|
|
except re.error as e:
|
|
return {"error": f"Invalid regex pattern: {e}"}
|
|
|
|
search_paths = list(Path(directory).rglob("*"))
|
|
|
|
for path in search_paths:
|
|
if path.is_file() and not path.is_symlink():
|
|
try:
|
|
with open(path, 'r', errors='ignore') as f:
|
|
for line_num, line in enumerate(f, 1):
|
|
if regex.search(line):
|
|
results["matches"].append({
|
|
"file": str(path),
|
|
"line": line_num,
|
|
"content": line.strip()
|
|
})
|
|
results["searched"] += 1
|
|
except Exception:
|
|
continue
|
|
|
|
results["count"] = len(results["matches"])
|
|
|
|
if output_file:
|
|
with open(output_file, 'w') as f:
|
|
json.dump(results, f, indent=2)
|
|
|
|
return results
|
|
|
|
def main():
|
|
if len(sys.argv) < 3:
|
|
print(__doc__)
|
|
sys.exit(1)
|
|
|
|
directory = sys.argv[1]
|
|
pattern = sys.argv[2]
|
|
output_file = sys.argv[3] if len(sys.argv) > 3 else None
|
|
|
|
if not os.path.isdir(directory):
|
|
print(f"Error: {directory} is not a valid directory")
|
|
sys.exit(1)
|
|
|
|
results = search_files(directory, pattern, output_file)
|
|
|
|
if "error" in results:
|
|
print(f"Error: {results['error']}")
|
|
sys.exit(1)
|
|
|
|
print(f"Searched {results['searched']} files")
|
|
print(f"Found {results['count']} matches")
|
|
|
|
for match in results["matches"][:10]:
|
|
print(f"\n{match['file']}:{match['line']}")
|
|
print(f" {match['content'][:100]}...")
|
|
|
|
if results['count'] > 10:
|
|
print(f"\n... and {results['count'] - 10} more matches")
|
|
|
|
if output_file:
|
|
print(f"\nFull results written to: {output_file}")
|
|
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |