Skip to content

Instantly share code, notes, and snippets.

@Saik0s
Last active December 20, 2025 09:23
Show Gist options
  • Select an option

  • Save Saik0s/c47e1eaf3bb077cee558b1e8e196665e to your computer and use it in GitHub Desktop.

Select an option

Save Saik0s/c47e1eaf3bb077cee558b1e8e196665e to your computer and use it in GitHub Desktop.
Interactive ComfyUI model sync from Google Drive with rclone
#!/bin/bash
#
# Interactive Model Sync from Google Drive
# Usage: ./sync-models.sh [destination_path]
#
set -e
DEST_PATH="${1:-./models}"
REMOTE_NAME="drive"
REMOTE_PATH="models"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
print_header() {
echo -e "${CYAN}"
echo "╔═══════════════════════════════════════════════════════════════╗"
echo "║ ComfyUI Model Sync from Google Drive ║"
echo "╚═══════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
}
print_step() {
echo -e "${BLUE}▶ $1${NC}"
}
print_success() {
echo -e "${GREEN}✓ $1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠ $1${NC}"
}
print_error() {
echo -e "${RED}✗ $1${NC}"
}
# Check and install rclone
install_rclone() {
if command -v rclone &> /dev/null; then
print_success "rclone is already installed ($(rclone version | head -1))"
return 0
fi
print_step "Installing rclone..."
if [[ "$OSTYPE" == "darwin"* ]]; then
if command -v brew &> /dev/null; then
brew install rclone
else
curl https://rclone.org/install.sh | sudo bash
fi
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
curl https://rclone.org/install.sh | sudo bash
else
print_error "Unsupported OS. Install rclone manually: https://rclone.org/install/"
exit 1
fi
print_success "rclone installed"
}
# Check if running headless
is_headless() {
if [[ -z "$DISPLAY" ]] || [[ -n "$SSH_CLIENT" && -z "$DISPLAY" ]]; then
return 0
fi
return 1
}
# Configure rclone for Google Drive
configure_rclone() {
local config_file
config_file=$(rclone config file 2>/dev/null | grep -v "^Configuration" | head -1)
print_step "Config file: ${config_file:-default location}"
local existing_remotes
existing_remotes=$(rclone listremotes 2>/dev/null)
if [[ -z "$existing_remotes" ]]; then
echo " No remotes configured"
else
echo " Found remotes: $(echo $existing_remotes | tr '\n' ' ')"
fi
# Check if drive remote exists and works
if echo "$existing_remotes" | grep -q "^${REMOTE_NAME}:$"; then
print_step "Testing '${REMOTE_NAME}:' connection..."
if rclone lsd "${REMOTE_NAME}:" &> /dev/null; then
print_success "Google Drive connected"
return 0
else
print_warning "Remote exists but connection failed"
read -p "Delete and reconfigure? [y/N]: " confirm
if [[ ! "$confirm" =~ ^[Yy] ]]; then
exit 1
fi
rclone config delete "${REMOTE_NAME}" 2>/dev/null || true
fi
fi
print_step "Configuring Google Drive access..."
echo ""
if is_headless; then
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN} HEADLESS AUTHENTICATION${NC}"
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
echo ""
echo -e "${GREEN}Step 1:${NC} On your LOCAL machine (with browser), run:"
echo -e " ${CYAN}rclone authorize \"drive\"${NC}"
echo ""
echo -e "${GREEN}Step 2:${NC} Complete Google sign-in in browser"
echo ""
echo -e "${GREEN}Step 3:${NC} Copy the token rclone prints"
echo ""
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
echo ""
echo -e "${YELLOW}Now running 'rclone config' - answer 'n' to browser question${NC}"
echo -e "${YELLOW}and paste your token at the config_token> prompt${NC}"
echo ""
read -p "Press Enter when ready..."
rclone config
else
echo -e "${YELLOW}Opening browser for authentication...${NC}"
rclone config create "${REMOTE_NAME}" drive
fi
# Verify
print_step "Verifying connection..."
if rclone lsd "${REMOTE_NAME}:" &> /dev/null; then
print_success "Google Drive configured"
else
print_error "Configuration failed"
exit 1
fi
}
# Main
main() {
print_header
install_rclone
configure_rclone
print_step "Fetching models from Google Drive..."
# Get list into array - simple and reliable
local models_raw
models_raw=$(rclone lsf "${REMOTE_NAME}:${REMOTE_PATH}" -R 2>/dev/null | grep -E '\.(safetensors|pth|pt|gguf|onnx|bin)$' | sort)
if [[ -z "$models_raw" ]]; then
print_error "No models found in ${REMOTE_NAME}:${REMOTE_PATH}"
exit 1
fi
# Convert to array
local -a MODELS
while IFS= read -r line; do
[[ -n "$line" ]] && MODELS+=("$line")
done <<< "$models_raw"
print_success "Found ${#MODELS[@]} models"
echo ""
# Print numbered list
echo -e "${CYAN}Available models:${NC}"
echo "─────────────────────────────────────────────────────────────────"
local i=1
for model in "${MODELS[@]}"; do
echo -e " ${YELLOW}${i}${NC}) ${model}"
i=$((i + 1))
done
echo ""
echo "Enter numbers separated by spaces (e.g., 1 3 5)"
echo "Or 'all' to download everything, 'q' to quit"
echo ""
read -p "> " INPUT
[[ "$INPUT" = "q" ]] && exit 0
# Build download list
local -a TO_DOWNLOAD
if [[ "$INPUT" = "all" ]]; then
TO_DOWNLOAD=("${MODELS[@]}")
else
for num in $INPUT; do
local idx=$((num - 1))
if [[ $idx -ge 0 ]] && [[ $idx -lt ${#MODELS[@]} ]]; then
TO_DOWNLOAD+=("${MODELS[$idx]}")
fi
done
fi
if [[ ${#TO_DOWNLOAD[@]} -eq 0 ]]; then
print_warning "Nothing selected"
exit 0
fi
echo ""
print_step "Downloading ${#TO_DOWNLOAD[@]} model(s) to ${DEST_PATH}..."
mkdir -p "$DEST_PATH"
local current=0
for model in "${TO_DOWNLOAD[@]}"; do
current=$((current + 1))
echo ""
echo -e "${BLUE}[$current/${#TO_DOWNLOAD[@]}]${NC} $model"
local dir
dir=$(dirname "$model")
mkdir -p "${DEST_PATH}/${dir}"
rclone copy "${REMOTE_NAME}:${REMOTE_PATH}/${model}" "${DEST_PATH}/${dir}" -P
done
echo ""
print_success "All downloads complete!"
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment