🐍 Python 3.10+
Backup The npm cache to Zip (Python)
Zips up the current contents of the npm cache before you run a cleanup against it.
backup_npm_cache_to_zip.py
#!/usr/bin/env python3
"""
backup_npm_cache_to_zip.py
Backs up the npm cache to a timestamped zip archive before you clear it.
Usage:
python backup_npm_cache_to_zip.py <destination_folder>
"""
import os
import sys
import zipfile
from datetime import datetime
from pathlib import Path
def main() -> None:
if len(sys.argv) < 2:
sys.exit("Usage: python backup_npm_cache_to_zip.py <destination_folder>")
source = Path(os.path.expandvars(r'%APPDATA%\npm-cache'))
destination_folder = Path(sys.argv[1])
if not source.exists():
print(f"{source} does not exist on this machine.")
return
destination_folder.mkdir(parents=True, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
zip_path = destination_folder / f"npm_cache_{timestamp}.zip"
# Zip file-by-file (rather than shutil.make_archive) so a single locked
# or in-use file doesn't abort the whole backup — it's just skipped.
added, skipped = 0, 0
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
for file in source.rglob("*"):
if not file.is_file():
continue
try:
zf.write(file, file.relative_to(source))
added += 1
except OSError:
skipped += 1
print(f"Backed up to {zip_path} ({added} file(s) added, {skipped} skipped)")
if __name__ == "__main__":
main()