env-backup
Back up .env files found via Everything CLI (es.exe) into env-files/.
Metadata
- Author: ropean, Claude Sonnet (Anthropic)
- Version: 1.0.0
- Dependencies: Everything (es.exe)
Code
python
#!/usr/bin/env python3
"""
@title env-backup
@description Back up .env files found via Everything CLI (es.exe) into env-files/.
@author ropean, Claude Sonnet (Anthropic)
@version 1.0.0
Runs: es.exe wfn:.env !path:win-dotfiles
and copies results into env-files/, organised by project name.
@example
python scripts/env-backup.py [--es-path PATH] [--query QUERY] [-o DIR] [--dry-run]
Options:
--es-path PATH Path to es.exe (auto-detected if omitted)
--query QUERY Everything search query
-o / --output Target directory (default: env-files/ in repo root)
--dry-run Show what would be copied without copying
@requires Everything (es.exe)
"""
import argparse
import shlex
import shutil
import subprocess
import sys
from pathlib import Path
SCRIPTS_DIR = Path(__file__).resolve().parent
REPO_ROOT = SCRIPTS_DIR.parent
DEFAULT_OUT = REPO_ROOT / "env-files"
DEFAULT_QUERY = "wfn:.env !path:win-dotfiles"
ES_CANDIDATE_PATHS = [
REPO_ROOT / "bin" / "es.exe",
Path("C:/Program Files/Everything/es.exe"),
Path("C:/Program Files (x86)/Everything/es.exe"),
]
EXCLUDE_PATTERNS = ["/scoop/", "/.vscode/", "/.cursor/", "appdata/local", "$recycle.bin"]
COMMON_CONFIG_DIRS = {"env", "config", "configs", ".config", "environments", "settings"}
# ── Everything ────────────────────────────────────────────────────────────────
def find_es() -> Path | None:
"""Locate es.exe: PATH first, then common install locations."""
in_path = shutil.which("es") or shutil.which("es.exe")
if in_path:
return Path(in_path)
for p in ES_CANDIDATE_PATHS:
if p.exists():
return p
return None
def query_everything(es: Path, query: str) -> list[str]:
cmd = [str(es)] + shlex.split(query)
result = subprocess.run(cmd, capture_output=True, text=True,
encoding="utf-8", errors="replace")
if result.returncode != 0:
stderr = result.stderr.strip()
if not stderr or "IPC" in stderr or "Everything" in stderr:
print("[error] Cannot connect to Everything — is it running?", file=sys.stderr)
else:
print(f"[error] es.exe: {stderr}", file=sys.stderr)
sys.exit(1)
return [l.strip() for l in result.stdout.splitlines() if l.strip()]
# ── File helpers ──────────────────────────────────────────────────────────────
def should_exclude(path: str) -> bool:
normalized = path.replace("\\", "/").lower()
return any(pat in normalized for pat in EXCLUDE_PATTERNS)
def project_name(src: Path) -> str:
parent = src.parent
if parent.name.lower() in COMMON_CONFIG_DIRS:
return parent.parent.name
return parent.name
# ── Main ──────────────────────────────────────────────────────────────────────
def parse_args() -> argparse.Namespace:
p = argparse.ArgumentParser(
description="Back up .env files via Everything CLI (es.exe)."
)
p.add_argument("--es-path", metavar="PATH",
help="Path to es.exe (auto-detected if omitted)")
p.add_argument("--query", default=DEFAULT_QUERY,
help=f"Everything search query (default: {DEFAULT_QUERY!r})")
p.add_argument("-o", "--output", default=str(DEFAULT_OUT), metavar="DIR",
help=f"Target directory (default: {DEFAULT_OUT.name}/)")
p.add_argument("--dry-run", action="store_true",
help="Print actions without copying")
return p.parse_args()
def main() -> None:
args = parse_args()
# ── Resolve es.exe ────────────────────────────────────────────────────────
if args.es_path:
es = Path(args.es_path)
if not es.exists():
print(f"[error] es.exe not found at: {es}", file=sys.stderr)
sys.exit(1)
else:
es = find_es()
if es is None:
print(
"[error] es.exe not found.\n"
" • Ensure Everything is installed and es.exe is in PATH, or\n"
" • specify its location: --es-path \"C:\\...\\es.exe\"",
file=sys.stderr,
)
sys.exit(1)
print(f"[es] {es}", file=sys.stderr)
print(f"[query] {args.query}", file=sys.stderr)
# ── Query ─────────────────────────────────────────────────────────────────
paths = query_everything(es, args.query)
print(f"[found] {len(paths)} file(s)\n", file=sys.stderr)
out_dir = Path(args.output)
ok = skip = fail = 0
for raw in paths:
src = Path(raw)
if should_exclude(raw):
print(f" skip {raw}", file=sys.stderr)
skip += 1
continue
name = project_name(src)
dst = out_dir / name / src.name
if args.dry_run:
print(f" dry {src} → {dst}")
ok += 1
continue
try:
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst)
print(f" ✓ {name}/{src.name}")
ok += 1
except OSError as e:
print(f" ✗ {raw}: {e}", file=sys.stderr)
fail += 1
print(f"\n[done] {ok} copied, {skip} skipped, {fail} failed", file=sys.stderr)
if __name__ == "__main__":
main()File Information
- Filename:
env-backup.py - Category: python
- Language: PYTHON