#!/usr/bin/env bash # keepass_to_pass # --------------- # Pipeline: exporta entries del KeePassXC database a `pass`. # # Cada entry queda en pass como multilinea: # # user: # url: # notes: # # Path en pass: /. Espacios reemplazados por `_`. # # REQUIERE: # - keepassxc-cli, pass, jq # - KEEPASS_DB (env) # - master password en pass meta/keepassxc-master o env KEEPASS_PASSWORD # # USO: # ./fn run keepass_to_pass [--prefix keepass] [--overwrite] [--dry-run] # # FLAGS: # --prefix

Prefijo en pass (default: keepass) # --overwrite Sobreescribe entradas existentes en pass # --dry-run No escribe; solo lista lo que haria set -euo pipefail REGISTRY_ROOT="${FN_REGISTRY_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)}" # shellcheck disable=SC1091 source "$REGISTRY_ROOT/bash/functions/infra/keepass_dump.sh" # shellcheck disable=SC1091 source "$REGISTRY_ROOT/bash/functions/infra/pass_set.sh" prefix="keepass" overwrite=0 dry_run=0 while [ $# -gt 0 ]; do case "$1" in --prefix) prefix="$2"; shift 2 ;; --overwrite) overwrite=1; shift ;; --dry-run) dry_run=1; shift ;; -h|--help) grep '^#' "$0" | sed 's/^# \?//' exit 0 ;; *) echo "keepass_to_pass: flag desconocido: $1" >&2; exit 1 ;; esac done echo "==> Dumping KeePassXC database..." dump=$(keepass_dump) total=$(printf '%s' "$dump" | jq 'length') echo "==> Found $total entries" imported=0 skipped=0 empty=0 i=0 while IFS= read -r entry; do i=$((i+1)) path=$(printf '%s' "$entry" | jq -r '.path') password=$(printf '%s' "$entry" | jq -r '.password') username=$(printf '%s' "$entry" | jq -r '.username') url=$(printf '%s' "$entry" | jq -r '.url') notes=$(printf '%s' "$entry" | jq -r '.notes') if [ -z "$path" ] || [ "$path" = "null" ]; then empty=$((empty+1)) continue fi if [ -z "$password" ] || [ "$password" = "null" ]; then empty=$((empty+1)) continue fi pass_path="$prefix/$path" if [ "$overwrite" -eq 0 ] && [ -f "${PASSWORD_STORE_DIR:-$HOME/.password-store}/$pass_path.gpg" ]; then skipped=$((skipped+1)) printf '[%d/%d] SKIP %s (existe)\n' "$i" "$total" "$pass_path" continue fi multiline="$password" [ -n "$username" ] && [ "$username" != "null" ] && multiline+=$'\nuser: '"$username" [ -n "$url" ] && [ "$url" != "null" ] && multiline+=$'\nurl: '"$url" [ -n "$notes" ] && [ "$notes" != "null" ] && multiline+=$'\nnotes: '"$notes" if [ "$dry_run" -eq 1 ]; then printf '[%d/%d] DRY %s\n' "$i" "$total" "$pass_path" else if pass_set "$pass_path" "$multiline"; then imported=$((imported+1)) printf '[%d/%d] IMPORT %s\n' "$i" "$total" "$pass_path" else printf '[%d/%d] FAIL %s\n' "$i" "$total" "$pass_path" >&2 fi fi done < <(printf '%s' "$dump" | jq -c '.[]') echo "==> Done: imported=$imported skipped=$skipped empty=$empty total=$total"