Files
claudeskill/skills/minio-upload/scripts/upload_to_obsidian.sh
Misaka Company 45c8623666 Add mutual exclusion validation for conflict handling options
Ensure --force, --skip, --backup, --rename options are used exclusively
to prevent ambiguous conflict resolution behavior.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-28 14:05:32 +08:00

211 lines
6.3 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
#
# Upload files to MinIO obsidian bucket
# Usage: upload_to_obsidian.sh <file_path> [subpath] [options]
#
# Arguments:
# file_path - Path to the file to upload
# subpath - Optional subpath/vault within obsidian bucket (default: main)
#
# Options:
# --force - Overwrite existing files without prompting
# --skip - Skip upload if file already exists
# --backup - Backup existing file before overwriting (.bak extension)
# --rename - Automatically rename if file exists (adds numeric suffix)
#
# Examples:
# upload_to_obsidian.sh temp/file.md
# upload_to_obsidian.sh temp/file.md journal
# upload_to_obsidian.sh temp/file.md main --force
# upload_to_obsidian.sh temp/file.md work --skip
set -e
# Initialize variables
FORCE=false
SKIP=false
BACKUP=false
RENAME=false
FILE_PATH=""
SUBPATH="main"
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--force)
FORCE=true
shift
;;
--skip)
SKIP=true
shift
;;
--backup)
BACKUP=true
shift
;;
--rename)
RENAME=true
shift
;;
-*)
echo "Error: Unknown option '$1'" >&2
echo "Usage: $0 <file_path> [subpath] [--force|--skip|--backup|--rename]" >&2
exit 1
;;
*)
if [ -z "$FILE_PATH" ]; then
FILE_PATH="$1"
elif [ "$SUBPATH" = "main" ]; then
SUBPATH="$1"
else
echo "Error: Too many arguments" >&2
exit 1
fi
shift
;;
esac
done
# Validate mutual exclusion of conflict handling options
CONFLICT_OPTS_COUNT=0
[ "$FORCE" = true ] && CONFLICT_OPTS_COUNT=$((CONFLICT_OPTS_COUNT + 1))
[ "$SKIP" = true ] && CONFLICT_OPTS_COUNT=$((CONFLICT_OPTS_COUNT + 1))
[ "$BACKUP" = true ] && CONFLICT_OPTS_COUNT=$((CONFLICT_OPTS_COUNT + 1))
[ "$RENAME" = true ] && CONFLICT_OPTS_COUNT=$((CONFLICT_OPTS_COUNT + 1))
if [ $CONFLICT_OPTS_COUNT -gt 1 ]; then
echo "Error: Conflict handling options are mutually exclusive." >&2
echo "Use only one of: --force, --skip, --backup, --rename" >&2
exit 1
fi
# Check file path argument
if [ -z "$FILE_PATH" ]; then
echo "Usage: $0 <file_path> [subpath] [--force|--skip|--backup|--rename]" >&2
exit 1
fi
# Validate file exists
if [ ! -f "$FILE_PATH" ]; then
echo "Error: File '$FILE_PATH' does not exist" >&2
exit 1
fi
# Get filename
FILENAME=$(basename "$FILE_PATH")
# Construct target path
TARGET_PATH="minio/obsidian/${SUBPATH}/${FILENAME}"
# Ensure subpath ends without trailing slash for mc
TARGET_PATH=$(echo "$TARGET_PATH" | sed 's://*:/:g')
# Check if file already exists
if mc stat "$TARGET_PATH" >/dev/null 2>&1; then
# User explicitly specified --skip
if [ "$SKIP" = true ]; then
echo " File already exists, skipping upload: $TARGET_PATH"
exit 0
fi
# User explicitly specified --backup
if [ "$BACKUP" = true ]; then
BACKUP_PATH="${TARGET_PATH}.bak"
echo "📦 Backing up existing file: $TARGET_PATH -> $BACKUP_PATH"
mc cp "$TARGET_PATH" "$BACKUP_PATH"
# User explicitly specified --rename
elif [ "$RENAME" = true ]; then
COUNTER=1
BASE_NAME="${FILENAME%.*}"
EXT="${FILENAME##*.}"
if [ "$BASE_NAME" = "$EXT" ]; then
# No extension
BASE_NAME="$FILENAME"
EXT=""
else
EXT=".$EXT"
fi
while true; do
NEW_NAME="${BASE_NAME}-${COUNTER}${EXT}"
NEW_TARGET="minio/obsidian/${SUBPATH}/${NEW_NAME}"
if ! mc stat "$NEW_TARGET" >/dev/null 2>&1; then
TARGET_PATH="$NEW_TARGET"
FILENAME="$NEW_NAME"
echo "📝 Renamed to: $FILENAME"
break
fi
COUNTER=$((COUNTER + 1))
done
# User explicitly specified --force
elif [ "$FORCE" = true ]; then
echo "⚠️ Overwriting existing file: $TARGET_PATH"
else
# No explicit option - prompt user
echo ""
echo "⚠️ File '$FILENAME' already exists in vault '${SUBPATH}'"
echo "Target: $TARGET_PATH"
echo ""
echo "Choose an action:"
echo " [o] Overwrite - Replace existing file"
echo " [s] Skip - Cancel upload"
echo " [b] Backup - Backup existing file (.bak) then overwrite"
echo " [r] Rename - Upload with new name (adds numeric suffix)"
echo ""
while true; do
read -p "Your choice [o/s/b/r]: " choice
case "$choice" in
o|O|overwrite)
echo "Overwriting existing file..."
break
;;
s|S|skip)
echo "❌ Upload cancelled"
exit 0
;;
b|B|backup)
BACKUP_PATH="${TARGET_PATH}.bak"
echo "📦 Backing up existing file: $TARGET_PATH -> $BACKUP_PATH"
mc cp "$TARGET_PATH" "$BACKUP_PATH"
break
;;
r|R|rename)
COUNTER=1
BASE_NAME="${FILENAME%.*}"
EXT="${FILENAME##*.}"
if [ "$BASE_NAME" = "$EXT" ]; then
BASE_NAME="$FILENAME"
EXT=""
else
EXT=".$EXT"
fi
while true; do
NEW_NAME="${BASE_NAME}-${COUNTER}${EXT}"
NEW_TARGET="minio/obsidian/${SUBPATH}/${NEW_NAME}"
if ! mc stat "$NEW_TARGET" >/dev/null 2>&1; then
TARGET_PATH="$NEW_TARGET"
FILENAME="$NEW_NAME"
echo "📝 Renamed to: $FILENAME"
break 2
fi
COUNTER=$((COUNTER + 1))
done
;;
*)
echo "Invalid choice. Please enter o, s, b, or r"
;;
esac
done
fi
fi
# Upload file
mc cp "$FILE_PATH" "$TARGET_PATH"
echo "✅ Uploaded: $FILE_PATH -> $TARGET_PATH"