Add file conflict handling to minio-upload skill

Implement comprehensive file conflict detection and resolution:
- Check for existing files before upload using mc stat (fixes mc ls bug)
- Interactive prompt when conflict detected: overwrite, skip, backup, rename
- Command-line options for non-interactive use: --force, --skip, --backup, --rename
- Auto-rename with numeric suffix when file exists
- Backup existing files with .bak extension before overwriting
- Update SKILL.md with conflict handling documentation and examples

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Misaka Company
2026-01-28 13:45:43 +08:00
parent cbe3cfccba
commit 51eae214cc
2 changed files with 208 additions and 12 deletions

View File

@@ -1,28 +1,78 @@
#!/bin/bash
#
# Upload files to MinIO obsidian bucket
# Usage: upload_to_obsidian.sh <file_path> [subpath]
# Usage: upload_to_obsidian.sh <file_path> [subpath] [options]
#
# Arguments:
# file_path - Path to the file to upload
# subpath - Optional subpath within obsidian bucket (default: main)
# 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 notes/2024
# upload_to_obsidian.sh temp/file.md "archive/old projects"
# 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
# Check arguments
if [ $# -lt 1 ]; then
echo "Usage: $0 <file_path> [subpath]" >&2
# 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
# Check file path argument
if [ -z "$FILE_PATH" ]; then
echo "Usage: $0 <file_path> [subpath] [--force|--skip|--backup|--rename]" >&2
exit 1
fi
FILE_PATH="$1"
SUBPATH="${2:-main}" # Default to 'main' if not specified
# Validate file exists
if [ ! -f "$FILE_PATH" ]; then
echo "Error: File '$FILE_PATH' does not exist" >&2
@@ -38,6 +88,109 @@ 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"