Skip to content

dotfile

Copy config files into the dotfiles/ directory, organized by project.

Metadata

  • Author: ropean, Claude Sonnet (Anthropic)
  • Version: 1.0.0

Code

python
#!/usr/bin/env python3
"""
@title dotfile
@description Copy config files into the dotfiles/ directory, organized by project.
@author ropean, Claude Sonnet (Anthropic)
@version 1.0.0

Supports glob patterns and unquoted paths with spaces.

@example
    python scripts/dotfile.py <path> [<path> ...]
    python scripts/dotfile.py D:\\Git\\project\\env\\.env
    python scripts/dotfile.py D:\\Git\\project\\config\\*.json
    python scripts/dotfile.py C:\\Program Files\\App\\config.xml
"""

import sys
import shutil
from glob import glob
from pathlib import Path

SCRIPTS_DIR = Path(__file__).resolve().parent
DOTFILES_DIR = SCRIPTS_DIR.parent / "dotfiles"
COMMON_CONFIG_DIRS = {"env", "config", "configs", ".config", "environments", "settings"}


# ── Helpers ───────────────────────────────────────────────────────────────────

def target_path(src: Path) -> Path:
    parent = src.parent
    if parent.name.lower() in COMMON_CONFIG_DIRS:
        project = parent.parent.name
    else:
        project = parent.name
    return DOTFILES_DIR / project / src.name


def copy_file(src: Path) -> bool:
    if not src.exists():
        print(f"  ✗  not found: {src}", file=sys.stderr)
        return False
    if not src.is_file():
        print(f"  ✗  not a file: {src}", file=sys.stderr)
        return False
    dst = target_path(src)
    try:
        dst.parent.mkdir(parents=True, exist_ok=True)
        shutil.copy2(src, dst)
        print(f"  ✓  {src}")
        print(f"     → {dst}")
        return True
    except OSError as e:
        print(f"  ✗  {src}: {e}", file=sys.stderr)
        return False


def expand_args(args: list[str]) -> list[Path]:
    """
    Expand glob patterns; merge consecutive tokens that form a path with spaces.
    """
    files: list[Path] = []
    i = 0
    while i < len(args):
        # Try progressively longer merges to handle unquoted paths with spaces
        merged = args[i]
        j = i + 1
        while j < len(args):
            candidate = merged + " " + args[j]
            if Path(candidate).exists() or any(c in candidate for c in ("*", "?")):
                merged = candidate
                j += 1
                if Path(merged).exists():
                    break
            else:
                break

        matches = glob(merged, recursive=True)
        if matches:
            files.extend(Path(m) for m in matches if Path(m).is_file())
        else:
            files.append(Path(merged))  # let copy_file report missing

        i = j if j > i + 1 else i + 1

    return files


# ── Main ──────────────────────────────────────────────────────────────────────

def main() -> None:
    args = sys.argv[1:]
    if not args:
        print("Usage: python scripts/dotfile.py <path> [<path> ...]")
        print("       Supports glob patterns and unquoted paths with spaces.")
        sys.exit(1)

    print(f"Dotfiles directory: {DOTFILES_DIR}\n")

    files = expand_args(args)
    ok = sum(copy_file(f) for f in files)
    print(f"\n[done] {ok}/{len(files)} copied")


if __name__ == "__main__":
    main()

File Information

  • Filename: dotfile.py
  • Category: python
  • Language: PYTHON

View on GitHub