mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 15:23:03 +02:00
feat: sync keepassxc files
This commit is contained in:
parent
33a320acc0
commit
ade22b74d4
124
scripts/utils/find_keepassxc.sh
Executable file
124
scripts/utils/find_keepassxc.sh
Executable file
@ -0,0 +1,124 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Find all KeePassXC database files (.kdbx) on the system and move them to a single location
|
||||||
|
# Uses 'fd' for fast searching - install with: sudo pacman -S fd
|
||||||
|
#
|
||||||
|
# Usage: ./find_keepassxc.sh [destination_directory]
|
||||||
|
# Default destination: ~/Keepass
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Source common library if available
|
||||||
|
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
||||||
|
if [[ -f "$SCRIPT_DIR/../lib/common.sh" ]]; then
|
||||||
|
# shellcheck source=../lib/common.sh
|
||||||
|
source "$SCRIPT_DIR/../lib/common.sh"
|
||||||
|
else
|
||||||
|
log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
DEST_DIR="${1:-$HOME/Keepass}"
|
||||||
|
SEARCH_ROOT="/"
|
||||||
|
TIMEOUT_SECONDS=30
|
||||||
|
|
||||||
|
# Ensure fd is installed
|
||||||
|
if ! command -v fd &>/dev/null; then
|
||||||
|
log "ERROR: 'fd' is not installed. Install with: sudo pacman -S fd"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create destination directory if it doesn't exist
|
||||||
|
mkdir -p "$DEST_DIR"
|
||||||
|
log "Destination directory: $DEST_DIR"
|
||||||
|
|
||||||
|
# Find all .kdbx files using fd (very fast, respects .gitignore by default, but we use -u for unrestricted)
|
||||||
|
# -e kdbx: search by extension
|
||||||
|
# -u: unrestricted (include hidden and ignored files)
|
||||||
|
# -a: absolute paths
|
||||||
|
# --one-file-system: don't cross filesystem boundaries (optional, remove if you want to search mounted drives)
|
||||||
|
log "Searching for .kdbx files across the system (timeout: ${TIMEOUT_SECONDS}s)..."
|
||||||
|
|
||||||
|
# Use timeout to ensure the search doesn't take too long
|
||||||
|
# Exclude /proc, /sys, /dev, /run, /tmp, /var/cache, /var/tmp for speed
|
||||||
|
FOUND_FILES=$(timeout "$TIMEOUT_SECONDS" fd \
|
||||||
|
-e kdbx \
|
||||||
|
-u \
|
||||||
|
-a \
|
||||||
|
--exclude '/proc' \
|
||||||
|
--exclude '/sys' \
|
||||||
|
--exclude '/dev' \
|
||||||
|
--exclude '/run' \
|
||||||
|
--exclude '/tmp' \
|
||||||
|
--exclude '/var/cache' \
|
||||||
|
--exclude '/var/tmp' \
|
||||||
|
--exclude '/snap' \
|
||||||
|
--exclude '/.snapshots' \
|
||||||
|
--exclude '/lost+found' \
|
||||||
|
. "$SEARCH_ROOT" 2>/dev/null || true)
|
||||||
|
|
||||||
|
if [[ -z "$FOUND_FILES" ]]; then
|
||||||
|
log "No .kdbx files found."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count and display found files
|
||||||
|
FILE_COUNT=$(echo "$FOUND_FILES" | wc -l)
|
||||||
|
log "Found $FILE_COUNT .kdbx file(s):"
|
||||||
|
echo "$FOUND_FILES" | while read -r file; do
|
||||||
|
echo " - $file"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Move files to destination
|
||||||
|
log "Moving files to $DEST_DIR..."
|
||||||
|
MOVED_COUNT=0
|
||||||
|
SKIPPED_COUNT=0
|
||||||
|
|
||||||
|
while IFS= read -r src_file; do
|
||||||
|
[[ -z "$src_file" ]] && continue
|
||||||
|
|
||||||
|
# Skip if file is already in destination
|
||||||
|
if [[ "$(dirname "$src_file")" == "$DEST_DIR" ]]; then
|
||||||
|
log "Skipping (already in destination): $src_file"
|
||||||
|
((SKIPPED_COUNT++)) || true
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the base filename
|
||||||
|
base_name=$(basename "$src_file")
|
||||||
|
dest_file="$DEST_DIR/$base_name"
|
||||||
|
|
||||||
|
# Handle filename conflicts by adding a number suffix
|
||||||
|
if [[ -f "$dest_file" ]]; then
|
||||||
|
# Check if it's the exact same file (by content)
|
||||||
|
if cmp -s "$src_file" "$dest_file"; then
|
||||||
|
log "Skipping (identical file exists): $src_file"
|
||||||
|
# Remove the duplicate source file
|
||||||
|
rm -v "$src_file"
|
||||||
|
((SKIPPED_COUNT++)) || true
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Different file with same name - add suffix
|
||||||
|
counter=1
|
||||||
|
name_without_ext="${base_name%.kdbx}"
|
||||||
|
while [[ -f "$dest_file" ]]; do
|
||||||
|
dest_file="$DEST_DIR/${name_without_ext} ($counter).kdbx"
|
||||||
|
((counter++))
|
||||||
|
done
|
||||||
|
log "Renaming to avoid conflict: $base_name -> $(basename "$dest_file")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Move the file
|
||||||
|
if mv -v "$src_file" "$dest_file"; then
|
||||||
|
((MOVED_COUNT++)) || true
|
||||||
|
else
|
||||||
|
log "ERROR: Failed to move $src_file"
|
||||||
|
fi
|
||||||
|
done <<<"$FOUND_FILES"
|
||||||
|
|
||||||
|
log "Done! Moved $MOVED_COUNT file(s), skipped $SKIPPED_COUNT file(s)."
|
||||||
|
log "All KeePassXC databases are now in: $DEST_DIR"
|
||||||
|
|
||||||
|
# List final contents
|
||||||
|
log "Contents of $DEST_DIR:"
|
||||||
|
ls -la "$DEST_DIR"/*.kdbx 2>/dev/null || log "No .kdbx files in destination"
|
||||||
173
scripts/utils/sync_keepassxc.sh
Executable file
173
scripts/utils/sync_keepassxc.sh
Executable file
@ -0,0 +1,173 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Merge all KeePassXC database files in a directory into a single database
|
||||||
|
# Merges databases one by one, deleting the source after each successful merge
|
||||||
|
# until only ONE database remains.
|
||||||
|
#
|
||||||
|
# IMPORTANT: You will be prompted for the master password for each database!
|
||||||
|
# Make sure all databases use the same master password, or know each password.
|
||||||
|
#
|
||||||
|
# Usage: ./sync_keepassxc.sh [directory]
|
||||||
|
# Default directory: ~/Keepass
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Source common library if available
|
||||||
|
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
||||||
|
if [[ -f "$SCRIPT_DIR/../lib/common.sh" ]]; then
|
||||||
|
# shellcheck source=../lib/common.sh
|
||||||
|
source "$SCRIPT_DIR/../lib/common.sh"
|
||||||
|
else
|
||||||
|
log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
KEEPASS_DIR="${1:-$HOME/Keepass}"
|
||||||
|
BACKUP_DIR="$KEEPASS_DIR/.backup_$(date +%Y%m%d_%H%M%S)"
|
||||||
|
|
||||||
|
# Ensure keepassxc-cli is installed
|
||||||
|
if ! command -v keepassxc-cli &>/dev/null; then
|
||||||
|
log "ERROR: 'keepassxc-cli' is not installed. Install with: sudo pacman -S keepassxc"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if directory exists
|
||||||
|
if [[ ! -d "$KEEPASS_DIR" ]]; then
|
||||||
|
log "ERROR: Directory does not exist: $KEEPASS_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find all .kdbx files
|
||||||
|
mapfile -t KDBX_FILES < <(find "$KEEPASS_DIR" -maxdepth 1 -name "*.kdbx" -type f | sort)
|
||||||
|
|
||||||
|
if [[ ${#KDBX_FILES[@]} -eq 0 ]]; then
|
||||||
|
log "No .kdbx files found in $KEEPASS_DIR"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#KDBX_FILES[@]} -eq 1 ]]; then
|
||||||
|
log "Only one .kdbx file found. Nothing to merge."
|
||||||
|
log "File: ${KDBX_FILES[0]}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Found ${#KDBX_FILES[@]} .kdbx files in $KEEPASS_DIR:"
|
||||||
|
for f in "${KDBX_FILES[@]}"; do
|
||||||
|
echo " - $(basename "$f")"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create backup directory
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
log "Creating backups in: $BACKUP_DIR"
|
||||||
|
|
||||||
|
# Backup all files before any operation
|
||||||
|
for f in "${KDBX_FILES[@]}"; do
|
||||||
|
cp -v "$f" "$BACKUP_DIR/"
|
||||||
|
done
|
||||||
|
log "All files backed up successfully."
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=============================================="
|
||||||
|
echo "WARNING: This will merge all databases into ONE"
|
||||||
|
echo "and DELETE the source files after each merge."
|
||||||
|
echo ""
|
||||||
|
echo "Backups are stored in: $BACKUP_DIR"
|
||||||
|
echo "=============================================="
|
||||||
|
echo ""
|
||||||
|
read -rp "Do you want to continue? (yes/no): " CONFIRM
|
||||||
|
if [[ "$CONFIRM" != "yes" ]]; then
|
||||||
|
log "Aborted by user."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Select the target database (the one to merge INTO)
|
||||||
|
# We'll use the first one alphabetically, or you could let user choose
|
||||||
|
TARGET_DB="${KDBX_FILES[0]}"
|
||||||
|
log "Target database (will contain all merged data): $(basename "$TARGET_DB")"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "You will need to enter the master password for the databases."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Read target database password
|
||||||
|
read -rsp "Enter master password for TARGET database ($(basename "$TARGET_DB")): " TARGET_PASSWORD
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Verify target password works
|
||||||
|
if ! echo "$TARGET_PASSWORD" | keepassxc-cli ls "$TARGET_DB" &>/dev/null; then
|
||||||
|
log "ERROR: Failed to open target database. Wrong password?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log "Target database password verified."
|
||||||
|
|
||||||
|
# Ask if all databases share the same password
|
||||||
|
echo ""
|
||||||
|
read -rp "Do ALL databases share the same master password? (y/n): " SAME_PASSWORD
|
||||||
|
SAME_PASSWORD="${SAME_PASSWORD,,}" # lowercase
|
||||||
|
|
||||||
|
# Merge each source database into the target
|
||||||
|
MERGE_COUNT=0
|
||||||
|
for ((i = 1; i < ${#KDBX_FILES[@]}; i++)); do
|
||||||
|
SOURCE_DB="${KDBX_FILES[$i]}"
|
||||||
|
log ""
|
||||||
|
log "Merging $(basename "$SOURCE_DB") into $(basename "$TARGET_DB")..."
|
||||||
|
|
||||||
|
# Reuse target password if user confirmed all are the same
|
||||||
|
if [[ "$SAME_PASSWORD" == "y" || "$SAME_PASSWORD" == "yes" ]]; then
|
||||||
|
SOURCE_PASSWORD="$TARGET_PASSWORD"
|
||||||
|
else
|
||||||
|
# Ask for source password (might be different)
|
||||||
|
echo ""
|
||||||
|
read -rsp "Enter master password for SOURCE database ($(basename "$SOURCE_DB")): " SOURCE_PASSWORD
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify source password
|
||||||
|
if ! echo "$SOURCE_PASSWORD" | keepassxc-cli ls "$SOURCE_DB" &>/dev/null; then
|
||||||
|
log "ERROR: Failed to open source database $(basename "$SOURCE_DB"). Wrong password?"
|
||||||
|
log "Skipping this database. You can try again later."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform the merge
|
||||||
|
# keepassxc-cli merge requires: target_db source_db
|
||||||
|
# It will prompt for passwords
|
||||||
|
if echo -e "${TARGET_PASSWORD}\n${SOURCE_PASSWORD}" | keepassxc-cli merge "$TARGET_DB" "$SOURCE_DB"; then
|
||||||
|
log "Successfully merged $(basename "$SOURCE_DB")"
|
||||||
|
|
||||||
|
# Delete the source database after successful merge
|
||||||
|
log "Deleting source database: $(basename "$SOURCE_DB")"
|
||||||
|
rm -v "$SOURCE_DB"
|
||||||
|
((MERGE_COUNT++)) || true
|
||||||
|
else
|
||||||
|
log "ERROR: Failed to merge $(basename "$SOURCE_DB")"
|
||||||
|
log "Source database NOT deleted. Check the backup and try manually."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
log "=============================================="
|
||||||
|
log "Merge complete!"
|
||||||
|
log "Merged $MERGE_COUNT database(s) into: $(basename "$TARGET_DB")"
|
||||||
|
log "Backups are preserved in: $BACKUP_DIR"
|
||||||
|
log "=============================================="
|
||||||
|
|
||||||
|
# Show final state
|
||||||
|
log ""
|
||||||
|
log "Remaining .kdbx files in $KEEPASS_DIR:"
|
||||||
|
find "$KEEPASS_DIR" -maxdepth 1 -name "*.kdbx" -type f -exec basename {} \;
|
||||||
|
|
||||||
|
# Rename to clean name if desired
|
||||||
|
FINAL_COUNT=$(find "$KEEPASS_DIR" -maxdepth 1 -name "*.kdbx" -type f | wc -l)
|
||||||
|
if [[ $FINAL_COUNT -eq 1 ]]; then
|
||||||
|
log ""
|
||||||
|
FINAL_NAME="$KEEPASS_DIR/Passwords.kdbx"
|
||||||
|
if [[ "$TARGET_DB" != "$FINAL_NAME" ]]; then
|
||||||
|
read -rp "Rename final database to 'Passwords.kdbx'? (y/n): " RENAME_CONFIRM
|
||||||
|
if [[ "$RENAME_CONFIRM" == "y" ]]; then
|
||||||
|
mv -v "$TARGET_DB" "$FINAL_NAME"
|
||||||
|
log "Final database: $FINAL_NAME"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
log ""
|
||||||
|
log "SUCCESS: You now have exactly ONE KeePassXC database!"
|
||||||
|
fi
|
||||||
Loading…
Reference in New Issue
Block a user