Veröffentlicht am 11. Februar 2026 von Dominic Böttger (vor 1 Monaten) · 15 Min. Lesezeit
Wer auf Arch Linux umgestiegen ist, aber weiterhin Zugriff auf SharePoint-Dokumentbibliotheken der Arbeit benötigt, hat vermutlich bemerkt, dass Microsoft keinen nativen OneDrive-Client für Linux anbietet. Unter Windows funktioniert ein Klick auf den “Sync”-Button in SharePoint einfach so. Unter Linux passiert nichts.
In dieser Anleitung zeige ich, wie man diesen “Sync”-Button unter Arch Linux zum Laufen bringt — komplett mit automatischer Drive-Erkennung, Unterordner-Synchronisation, Windows-artiger Ordnerbenennung und systemd-Hintergrunddiensten. Klick auf “Sync” im Browser, und die Dateien erscheinen in ~/SharePoint/.
Was wir bauen
Wenn man in SharePoint auf “Sync” bei einer Bibliothek oder einem Ordner klickt, löst SharePoint eine odopen://-Protokoll-URL aus. Wir richten ein:
- abraunegg/onedrive — den Open-Source OneDrive-Sync-Client für Linux
- Einen Protocol Handler (
odopen-handler.sh), derodopen://-URLs vom Browser abfängt - XDG Desktop-Integration, damit das System diese URLs an unseren Handler weiterleitet
- Systemd User Services für persistente Hintergrundsynchronisation
Das Endergebnis: Klick auf “Sync” in SharePoint, ein Terminal öffnet sich für die Ersteinrichtung, und danach synchronisieren die Dateien im Hintergrund — genau wie unter Windows.
Voraussetzungen
- Arch Linux (oder eine Arch-basierte Distribution)
- Ein AUR-Helper wie
yayoderparu python3(für URL-Dekodierung)notify-send(normalerweise bei der DE/WM dabei)- Ein Terminal-Emulator (alacritty, kitty, foot, etc.)
Schritt 1: abraunegg/onedrive installieren
Den OneDrive-Client aus dem AUR installieren:
yay -S onedrive-abraunegg
Das baut den Client aus dem Quellcode (er ist in D geschrieben, daher wird dmd als Build-Abhängigkeit benötigt).
Installation überprüfen:
onedrive --version
# onedrive v2.5.10
Schritt 2: Bei Microsoft authentifizieren
Eine einmalige Authentifizierung ist nötig, damit der Client ein Refresh Token erhalten kann. Wer nicht das gesamte persönliche OneDrive lokal synchronisieren möchte, kann die vollständige Synchronisation überspringen und nur eine einmalige Authentifizierung durchführen.
OneDrive starten und nach der Authentifizierung sofort abbrechen:
onedrive --sync --verbose
Das gibt eine URL aus — diese im Browser öffnen und sich mit dem Microsoft-Konto anmelden. Sobald die Authentifizierung abgeschlossen ist, mit Ctrl+C die Synchronisation stoppen. Das Refresh Token ist nun unter ~/.config/onedrive/refresh_token gespeichert.
Wer keine persönlichen OneDrive-Dateien lokal haben möchte, entfernt das Standard-Sync-Verzeichnis:
rm -rf ~/OneDrive
Der Standard-OneDrive-Dienst ist standardmäßig deaktiviert — er synchronisiert nicht im Hintergrund, es sei denn, man aktiviert ihn explizit:
# Überprüfen, dass er nicht läuft (sollte er nicht)
systemctl --user status onedrive
Schritt 3: Protocol Handler Script installieren
Das folgende Skript unter ~/.local/bin/odopen-handler.sh speichern:
#!/bin/bash
# =============================================================================
# odopen-handler.sh
# Protocol handler for odopen:// URLs (Teams/SharePoint "Sync" button)
# Uses abraunegg/onedrive as sync backend
# =============================================================================
set -euo pipefail
LOGFILE="$HOME/.local/share/odopen-handler/handler.log"
BASE_SYNC_DIR="$HOME/SharePoint"
BASE_CONFIG_DIR="$HOME/.config/onedrive-sharepoint"
mkdir -p "$(dirname "$LOGFILE")"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOGFILE"
}
# ---------------------------------------------------------------------------
# URL parsing helpers
# ---------------------------------------------------------------------------
urldecode() {
python3 -c "import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))" "$1"
}
parse_param() {
local value
value=$(echo "$1" | grep -oP "${2}=\K[^&]+" | head -1 || true)
if [[ -n "$value" ]]; then
urldecode "$value"
fi
}
# ---------------------------------------------------------------------------
# Notification helper (works with most DEs)
# ---------------------------------------------------------------------------
notify() {
if command -v notify-send &>/dev/null; then
notify-send -i folder-sync "OneDrive Sync" "$1"
fi
log "$1"
}
# ---------------------------------------------------------------------------
# --list: Show all active syncs
# ---------------------------------------------------------------------------
cmd_list() {
local found=0
for config_dir in "$BASE_CONFIG_DIR"/*/; do
[[ -d "$config_dir" ]] || continue
local name
name=$(basename "$config_dir")
local service_name="onedrive-sharepoint-${name}"
local sync_dir=""
local drive_id=""
local status="stopped"
if [[ -f "$config_dir/config" ]]; then
sync_dir=$(grep -oP 'sync_dir\s*=\s*"\K[^"]+' "$config_dir/config" || true)
drive_id=$(grep -oP 'drive_id\s*=\s*"\K[^"]+' "$config_dir/config" || true)
fi
if systemctl --user is-active "$service_name" &>/dev/null; then
status="running"
elif systemctl --user is-enabled "$service_name" &>/dev/null; then
status="enabled (stopped)"
fi
if [[ $found -eq 0 ]]; then
echo "Active OneDrive SharePoint syncs:"
echo ""
fi
found=$((found + 1))
echo " [$found] $name"
echo " Sync dir: $sync_dir"
echo " Drive ID: ${drive_id:-(not set)}"
echo " Service: $service_name ($status)"
echo ""
done
if [[ $found -eq 0 ]]; then
echo "No SharePoint syncs configured."
fi
}
# ---------------------------------------------------------------------------
# --unsync: Remove a sync configuration
# ---------------------------------------------------------------------------
cmd_unsync() {
local target="${1:-}"
# Collect available syncs
local names=()
for config_dir in "$BASE_CONFIG_DIR"/*/; do
[[ -d "$config_dir" ]] || continue
names+=("$(basename "$config_dir")")
done
if [[ ${#names[@]} -eq 0 ]]; then
echo "No SharePoint syncs configured."
exit 0
fi
# If no target given, show interactive picker
if [[ -z "$target" ]]; then
echo "Which sync do you want to remove?"
echo ""
for i in "${!names[@]}"; do
local n="${names[$i]}"
local sd=""
if [[ -f "$BASE_CONFIG_DIR/$n/config" ]]; then
sd=$(grep -oP 'sync_dir\s*=\s*"\K[^"]+' "$BASE_CONFIG_DIR/$n/config" || true)
fi
local svc_status="stopped"
if systemctl --user is-active "onedrive-sharepoint-${n}" &>/dev/null; then
svc_status="running"
fi
echo " [$((i + 1))] $n ($svc_status)"
[[ -n "$sd" ]] && echo " $sd"
done
echo ""
read -rp "Enter number (or 'q' to quit): " choice
[[ "$choice" == "q" || -z "$choice" ]] && exit 0
if ! [[ "$choice" =~ ^[0-9]+$ ]] || [[ "$choice" -lt 1 ]] || [[ "$choice" -gt ${#names[@]} ]]; then
echo "Invalid selection."
exit 1
fi
target="${names[$((choice - 1))]}"
fi
# Resolve target: allow passing display name, safe name, or sync dir name
local safe_target=""
for n in "${names[@]}"; do
local sd=""
if [[ -f "$BASE_CONFIG_DIR/$n/config" ]]; then
sd=$(grep -oP 'sync_dir\s*=\s*"\K[^"]+' "$BASE_CONFIG_DIR/$n/config" || true)
fi
# Match against: safe name, sync dir basename, or sync dir full path
if [[ "$n" == "$target" ]] || \
[[ "$(basename "$sd")" == "$target" ]] || \
[[ "$sd" == "$target" ]]; then
safe_target="$n"
break
fi
done
if [[ -z "$safe_target" ]]; then
echo "Error: No sync found for '$target'"
echo "Use --list to see available syncs."
exit 1
fi
local service_name="onedrive-sharepoint-${safe_target}"
local sync_dir=""
if [[ -f "$BASE_CONFIG_DIR/$safe_target/config" ]]; then
sync_dir=$(grep -oP 'sync_dir\s*=\s*"\K[^"]+' "$BASE_CONFIG_DIR/$safe_target/config" || true)
fi
echo ""
echo "Removing sync: $safe_target"
echo " Config: $BASE_CONFIG_DIR/$safe_target"
echo " Sync dir: $sync_dir"
echo " Service: $service_name"
echo ""
read -rp "Delete local files too? [y/N]: " delete_files
# Stop and disable service
systemctl --user stop "$service_name" 2>/dev/null || true
systemctl --user disable "$service_name" 2>/dev/null || true
rm -f "$HOME/.config/systemd/user/${service_name}.service"
systemctl --user daemon-reload
# Remove config
rm -rf "$BASE_CONFIG_DIR/$safe_target"
# Remove local files if requested
if [[ "$delete_files" =~ ^[yY]$ ]] && [[ -n "$sync_dir" ]]; then
rm -rf "$sync_dir"
echo "Removed local files: $sync_dir"
fi
echo "Sync '$safe_target' removed."
log "Unsynced: $safe_target"
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
case "${1:-}" in
--list)
cmd_list
exit 0
;;
--unsync)
cmd_unsync "${2:-}"
exit 0
;;
--help|-h)
echo "Usage:"
echo " odopen-handler.sh <odopen://...> Handle SharePoint sync URL"
echo " odopen-handler.sh --list List all active syncs"
echo " odopen-handler.sh --unsync [name] Remove a sync (interactive if no name)"
echo " odopen-handler.sh --help Show this help"
exit 0
;;
esac
URI="${1:-}"
if [[ -z "$URI" ]]; then
log "ERROR: No URI provided."
notify "Error: No odopen:// URL provided."
exit 1
fi
log "Received URI: $URI"
# --- Parse parameters from odopen:// URL ---
SITE_URL=$(parse_param "$URI" "webUrl")
FOLDER_URL=$(parse_param "$URI" "folderUrl")
FOLDER_NAME=$(parse_param "$URI" "folderName")
LIST_TITLE=$(parse_param "$URI" "listTitle")
WEB_TITLE=$(parse_param "$URI" "webTitle")
SITE_ID=$(parse_param "$URI" "siteId")
LIST_ID=$(parse_param "$URI" "listId")
WEB_ID=$(parse_param "$URI" "webId")
# Strip curly braces (SharePoint sometimes returns IDs with {})
SITE_ID="${SITE_ID//[\{\}]/}"
LIST_ID="${LIST_ID//[\{\}]/}"
WEB_ID="${WEB_ID//[\{\}]/}"
# --- Derive the relative folder path within the library ---
RELATIVE_FOLDER=""
if [[ -n "$FOLDER_URL" ]] && [[ -n "$SITE_URL" ]]; then
LIB_AND_FOLDER="${FOLDER_URL#"$SITE_URL"}"
LIB_AND_FOLDER="${LIB_AND_FOLDER#/}"
RELATIVE_FOLDER="${LIB_AND_FOLDER#*/}"
if [[ "$RELATIVE_FOLDER" == "$LIB_AND_FOLDER" ]]; then
RELATIVE_FOLDER=""
fi
fi
log "Parsed: site=$WEB_TITLE | library=$LIST_TITLE | folder=$FOLDER_NAME | relative_path=$RELATIVE_FOLDER"
log "Site URL: $SITE_URL"
log "Site ID: $SITE_ID | Web ID: $WEB_ID | List ID: $LIST_ID"
# --- Derive unique names - Windows-style "Sitename - Folder" ---
if [[ -n "$FOLDER_NAME" ]] && [[ -n "$RELATIVE_FOLDER" ]]; then
DISPLAY_NAME="${WEB_TITLE} - ${FOLDER_NAME}"
SAFE_NAME=$(echo "${WEB_TITLE}_${FOLDER_NAME}" | tr ' ' '_' | tr -cd '[:alnum:]_-')
SINGLE_DIR="$RELATIVE_FOLDER"
else
DISPLAY_NAME="${WEB_TITLE} - ${LIST_TITLE}"
SAFE_NAME=$(echo "${WEB_TITLE}_${LIST_TITLE}" | tr ' ' '_' | tr -cd '[:alnum:]_-')
SINGLE_DIR=""
fi
CONFIG_DIR="${BASE_CONFIG_DIR}/${SAFE_NAME}"
SYNC_DIR="${BASE_SYNC_DIR}/${DISPLAY_NAME}"
SERVICE_NAME="onedrive-sharepoint-${SAFE_NAME}"
log "Config dir: $CONFIG_DIR"
log "Sync dir: $SYNC_DIR"
log "Single dir: $SINGLE_DIR"
# --- Check if abraunegg/onedrive is installed ---
if ! command -v onedrive &>/dev/null; then
notify "Error: abraunegg/onedrive is not installed!\nInstall with: yay -S onedrive-abraunegg"
log "ERROR: onedrive not found in PATH"
exit 1
fi
# --- Check if this library is already configured ---
if [[ -d "$CONFIG_DIR" ]] && [[ -f "$CONFIG_DIR/config" ]]; then
notify "Sync for '$DISPLAY_NAME' is already configured.\nSync directory: $SYNC_DIR"
if systemctl --user is-active "$SERVICE_NAME" &>/dev/null; then
log "Service $SERVICE_NAME is already running."
notify "Sync is already running in the background."
else
log "Starting existing service $SERVICE_NAME..."
systemctl --user start "$SERVICE_NAME" || true
notify "Sync has been restarted."
fi
exit 0
fi
# --- Create new configuration ---
mkdir -p "$CONFIG_DIR"
mkdir -p "$SYNC_DIR"
log "Creating new onedrive config in $CONFIG_DIR"
# Create config without drive_id (will be determined in the first-run script)
cat > "$CONFIG_DIR/config" <<EOF
# OneDrive SharePoint Sync - $DISPLAY_NAME
# Auto-generated by odopen-handler.sh on $(date)
sync_dir = "$SYNC_DIR"
EOF
# Check if a default OneDrive profile exists (for token reuse)
DEFAULT_CONFIG="$HOME/.config/onedrive"
if [[ -f "$DEFAULT_CONFIG/refresh_token" ]]; then
log "Found existing OneDrive config, copying refresh_token..."
cp "$DEFAULT_CONFIG/refresh_token" "$CONFIG_DIR/refresh_token" 2>/dev/null || true
notify "Configuration created for: $DISPLAY_NAME\n\nDetermining Drive ID..."
else
log "No existing OneDrive config found. First-run will require authentication."
notify "New configuration created.\n\nAuthentication and Drive ID lookup in terminal..."
fi
# --- Build single-directory flags for onedrive CLI ---
SINGLE_DIR_FLAG=""
if [[ -n "$SINGLE_DIR" ]]; then
SINGLE_DIR_FLAG="--single-directory '$SINGLE_DIR'"
fi
# --- Create systemd user service ---
SERVICE_FILE="$HOME/.config/systemd/user/${SERVICE_NAME}.service"
mkdir -p "$(dirname "$SERVICE_FILE")"
EXEC_CMD="/usr/bin/onedrive --monitor --confdir=\"$CONFIG_DIR\""
if [[ -n "$SINGLE_DIR" ]]; then
EXEC_CMD="$EXEC_CMD --single-directory '$SINGLE_DIR'"
fi
cat > "$SERVICE_FILE" <<EOF
[Unit]
Description=OneDrive SharePoint Sync - $DISPLAY_NAME
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=$EXEC_CMD
Restart=on-failure
RestartSec=30
# Performance & Safety
Nice=10
IOSchedulingClass=idle
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
log "Created systemd service: $SERVICE_NAME"
# --- Open interactive terminal for first-run setup ---
# Write env file (avoids sed issues with special chars like & in site names)
FIRST_RUN_ENV=$(mktemp /tmp/odopen-firstrun-XXXXXX.env)
cat > "$FIRST_RUN_ENV" <<ENVEOF
CONFIG_DIR=$(printf '%q' "$CONFIG_DIR")
SERVICE_NAME=$(printf '%q' "$SERVICE_NAME")
WEB_TITLE=$(printf '%q' "$WEB_TITLE")
LIST_TITLE=$(printf '%q' "$LIST_TITLE")
DISPLAY_NAME=$(printf '%q' "$DISPLAY_NAME")
SYNC_DIR=$(printf '%q' "$SYNC_DIR")
SINGLE_DIR=$(printf '%q' "$SINGLE_DIR")
ENVEOF
FIRST_RUN_SCRIPT=$(mktemp /tmp/odopen-firstrun-XXXXXX.sh)
cat > "$FIRST_RUN_SCRIPT" <<'FIRSTRUN'
#!/bin/bash
# Source environment variables
ENV_FILE="${BASH_SOURCE[0]%.sh}.env"
if [[ -f "$ENV_FILE" ]]; then
source "$ENV_FILE"
else
echo "ERROR: Environment file not found: $ENV_FILE"
read
exit 1
fi
echo "======================================================="
echo " OneDrive SharePoint Sync - First-Run Setup"
echo "======================================================="
echo ""
echo " Team/Site: $WEB_TITLE"
echo " Library: $LIST_TITLE"
if [[ -n "$SINGLE_DIR" ]]; then
echo " Folder: $SINGLE_DIR"
fi
echo " Sync dir: $SYNC_DIR"
echo " Config: $CONFIG_DIR"
echo ""
# --- Step 1: Determine the Drive ID for this SharePoint library ---
echo "-------------------------------------------------------"
echo " Step 1: Determining Drive ID for '$WEB_TITLE'..."
echo " (First use: browser window will open for login)"
echo "-------------------------------------------------------"
echo ""
DRIVE_OUTPUT=$(onedrive --get-sharepoint-drive-id "$WEB_TITLE" 2>&1)
echo "$DRIVE_OUTPUT"
echo ""
if echo "$DRIVE_OUTPUT" | grep -q "ERROR"; then
echo "======================================================="
echo " ERROR: SharePoint site '$WEB_TITLE' not found."
echo " Check the site name and your permissions."
echo "======================================================="
echo ""
echo "Press Enter to close..."
read
exit 1
fi
# Extract drive_id - try exact match first, then auto-select if only one result
DRIVE_ID=$(echo "$DRIVE_OUTPUT" | grep -B1 "Library Name: *$LIST_TITLE" | grep -oP 'drive_id:\s+\K\S+' || true)
if [[ -z "$DRIVE_ID" ]]; then
DRIVE_ID_COUNT=$(echo "$DRIVE_OUTPUT" | grep -c 'drive_id:' || true)
if [[ "$DRIVE_ID_COUNT" -eq 1 ]]; then
DRIVE_ID=$(echo "$DRIVE_OUTPUT" | grep -oP 'drive_id:\s+\K\S+')
MATCHED_LIB=$(echo "$DRIVE_OUTPUT" | grep -oP 'Library Name:\s+\K.*')
echo " Auto-selected: '$MATCHED_LIB' (only library found)"
fi
fi
if [[ -z "$DRIVE_ID" ]]; then
echo "-------------------------------------------------------"
echo " Could not auto-match library '$LIST_TITLE'."
echo " Available Drive IDs are shown above."
echo ""
echo " Please enter the drive_id (e.g. b!xxxxxx):"
echo "-------------------------------------------------------"
read -r DRIVE_ID
if [[ -z "$DRIVE_ID" ]]; then
echo "No Drive ID entered. Aborting."
echo "Press Enter to close..."
read
exit 1
fi
fi
echo ""
echo " Found Drive ID: $DRIVE_ID"
echo ""
# --- Step 2: Update config with drive_id ---
echo "-------------------------------------------------------"
echo " Step 2: Updating configuration..."
echo "-------------------------------------------------------"
cat > "$CONFIG_DIR/config" <<EOF2
# OneDrive SharePoint Sync - $DISPLAY_NAME
# Auto-generated by odopen-handler.sh
sync_dir = "$SYNC_DIR"
drive_id = "$DRIVE_ID"
EOF2
echo " Config written: $CONFIG_DIR/config"
echo ""
# --- Step 3: Initial synchronization ---
echo "-------------------------------------------------------"
echo " Step 3: Starting initial sync..."
if [[ -n "$SINGLE_DIR" ]]; then
echo " Folder: $SINGLE_DIR"
fi
echo "-------------------------------------------------------"
echo ""
SYNC_CMD=(onedrive --confdir="$CONFIG_DIR" --sync --verbose --resync --resync-auth)
if [[ -n "$SINGLE_DIR" ]]; then
SYNC_CMD+=(--single-directory "$SINGLE_DIR")
fi
"${SYNC_CMD[@]}"
if [[ $? -eq 0 ]]; then
echo ""
echo "======================================================="
echo " Initial sync completed successfully!"
echo " Enabling background sync..."
echo "======================================================="
systemctl --user enable "$SERVICE_NAME"
systemctl --user start "$SERVICE_NAME"
echo ""
echo " Service status:"
systemctl --user status "$SERVICE_NAME" --no-pager || true
echo ""
echo " Your files are at: $SYNC_DIR"
echo ""
echo " Useful commands:"
echo " Status: systemctl --user status $SERVICE_NAME"
echo " Stop: systemctl --user stop $SERVICE_NAME"
echo " Logs: journalctl --user -u $SERVICE_NAME -f"
echo ""
else
echo ""
echo "======================================================="
echo " ERROR during synchronization."
echo " Check the output above for details."
echo ""
echo " Manual setup:"
echo " onedrive --confdir='$CONFIG_DIR' --sync --verbose"
echo "======================================================="
fi
echo "Press Enter to close..."
read
FIRSTRUN
# Rename env file to match the script name so the script can find it
mv "$FIRST_RUN_ENV" "${FIRST_RUN_SCRIPT%.sh}.env"
chmod +x "$FIRST_RUN_SCRIPT"
# Open terminal - try available terminal emulators
open_terminal() {
local cmd="$1"
if command -v kitty &>/dev/null; then
kitty --title "OneDrive Sync Setup" bash "$cmd" &
elif command -v alacritty &>/dev/null; then
alacritty --title "OneDrive Sync Setup" -e bash "$cmd" &
elif command -v foot &>/dev/null; then
foot --title "OneDrive Sync Setup" bash "$cmd" &
elif command -v gnome-terminal &>/dev/null; then
gnome-terminal --title "OneDrive Sync Setup" -- bash "$cmd" &
elif command -v konsole &>/dev/null; then
konsole -e bash "$cmd" &
elif command -v xterm &>/dev/null; then
xterm -title "OneDrive Sync Setup" -e bash "$cmd" &
else
log "ERROR: No terminal emulator found"
notify "No terminal found!\nPlease run manually:\nbash $cmd"
return 1
fi
}
open_terminal "$FIRST_RUN_SCRIPT"
log "Opened terminal for first-run setup."
Ausführbar machen:
chmod +x ~/.local/bin/odopen-handler.sh
Schritt 4: Den odopen:// Protocol Handler registrieren
Einen Desktop-Eintrag erstellen, damit das System weiß, wie odopen://-URLs verarbeitet werden:
cat > ~/.local/share/applications/odopen-handler.desktop <<EOF
[Desktop Entry]
Type=Application
Name=OneDrive Sync Handler
Comment=Protocol handler for odopen:// URLs (Teams/SharePoint Sync)
Exec=$HOME/.local/bin/odopen-handler.sh %u
MimeType=x-scheme-handler/odopen;
NoDisplay=true
Terminal=false
EOF
Beim System registrieren:
xdg-mime default odopen-handler.desktop x-scheme-handler/odopen
update-desktop-database ~/.local/share/applications/
Registrierung überprüfen:
xdg-mime query default x-scheme-handler/odopen
# Sollte ausgeben: odopen-handler.desktop
Schritt 5: Browser konfigurieren
Der Browser muss erlauben, dass odopen://-URLs externe Anwendungen öffnen:
- Firefox: Beim ersten Klick auf einen SharePoint “Sync”-Button fragt Firefox nach einer Anwendung. Den Handler auswählen und “Diese Auswahl merken” aktivieren.
- Chromium/Chrome/Edge: Möglicherweise muss das Protokoll in
chrome://settings/handlerserlaubt oder die Aufforderung beim ersten Erscheinen akzeptiert werden.
Verwendung
Eine SharePoint-Bibliothek oder einen Ordner synchronisieren
- Zu einer SharePoint-Dokumentbibliothek oder einem Ordner im Browser navigieren
- Auf den “Sync”-Button klicken
- Der Browser startet den Protocol Handler
- Ein Terminal-Fenster öffnet sich mit der Ersteinrichtung:
- Schritt 1: Abfrage der SharePoint-API nach der Drive ID
- Schritt 2: Konfiguration schreiben
- Schritt 3: Erste Synchronisation durchführen
- Nach der ersten Synchronisation startet ein systemd Service, der auf Änderungen überwacht
Die Dateien erscheinen in ~/SharePoint/ mit Windows-artiger Benennung:
| Was synchronisiert wird | Lokaler Ordner |
|---|---|
| Gesamte Bibliothek auf “Project Alpha” | ~/SharePoint/Project Alpha - Documents/ |
| Unterordner “Reports” auf “Project Alpha” | ~/SharePoint/Project Alpha - Reports/ |
Aktive Synchronisationen auflisten
odopen-handler.sh --list
Ausgabe:
Active OneDrive SharePoint syncs:
[1] ProjectAlpha_Reports
Sync dir: /home/user/SharePoint/Project Alpha - Reports
Drive ID: b!abc123...
Service: onedrive-sharepoint-ProjectAlpha_Reports (running)
Eine Synchronisation entfernen
Interaktiver Modus (zeigt eine Auswahl):
odopen-handler.sh --unsync
Oder den Namen direkt angeben:
odopen-handler.sh --unsync "Project Alpha - Reports"
Der unsync-Befehl wird:
- Den systemd Service stoppen und deaktivieren
- Das Konfigurationsverzeichnis entfernen
- Optional die lokalen Dateien löschen (es wird nachgefragt)
Nützliche systemd-Befehle
# Sync-Status prüfen
systemctl --user status onedrive-sharepoint-<name>
# Live-Sync-Logs ansehen
journalctl --user -u onedrive-sharepoint-<name> -f
# Sync temporär stoppen
systemctl --user stop onedrive-sharepoint-<name>
# Gestoppten Sync neustarten
systemctl --user start onedrive-sharepoint-<name>
Wie es unter der Haube funktioniert
Wenn man in SharePoint auf “Sync” klickt, öffnet der Browser eine URL wie:
odopen://sync?siteId={...}&webId={...}&webTitle=MyProject&listTitle=Documents
&folderName=Reports&folderUrl=https://tenant.sharepoint.com/sites/MyProject/...
Das Handler-Skript:
- Parst die URL, um den Site-Namen, den Bibliothekstitel, den Ordnernamen und den relativen Pfad zu extrahieren
- Leitet eine eindeutige Konfiguration ab aus den Site- und Ordnernamen und erstellt ein separates onedrive-Konfigurationsverzeichnis pro Synchronisation
- Fragt die SharePoint-API ab über
onedrive --get-sharepoint-drive-id, um die richtigedrive_idfür die Dokumentbibliothek zu finden - Behandelt lokalisierte Bibliotheksnamen — SharePoint sendet “Documents” in der URL, aber die API gibt möglicherweise “Dokumente” zurück. Das Skript wählt automatisch aus, wenn es nur eine Bibliothek gibt
- Erstellt einen systemd User Service, der
onedrive --monitormit dem spezifischen--confdirund optionalem--single-directory-Flag ausführt - Verwendet eine env-Datei statt sed für die Variablenübergabe an das Ersteinrichtungsskript, um Probleme mit Sonderzeichen wie
&in Site-Namen zu vermeiden
Fallstricke und Tipps
Das gesamte persönliche OneDrive nicht synchronisieren, wenn es nicht nötig ist. Der Standard-onedrive-Dienst ist deaktiviert. Nur SharePoint-Synchronisationen, die explizit über den “Sync”-Button eingerichtet werden, laufen.
Das Setup-Terminal fertig werden lassen. Wenn sich das Ersteinrichtungs-Terminal öffnet, alle drei Schritte abschließen lassen, bevor man es schließt. Die Drive ID wird während dieses Prozesses in die Konfiguration geschrieben.
SharePoint verwendet lokalisierte Namen. Der “Sync”-Button sendet englische Namen wie “Documents”, aber die API gibt lokalisierte Namen wie “Dokumente” zurück. Das Skript handhabt dies automatisch, wenn es nur eine Dokumentbibliothek auf der Site gibt.
Site-Namen mit Sonderzeichen funktionieren. Namen wie “Jung Garten & Landschaft” werden durch escapte Umgebungsvariablen korrekt behandelt.
Das Sync-Intervall beträgt standardmäßig 5 Minuten. Der onedrive-Client im Monitor-Modus prüft alle 300 Sekunden auf Änderungen. Das kann mit monitor_interval in der Konfigurationsdatei angepasst werden.
Datei-Indexer können Probleme verursachen. Wer Baloo oder Tracker nutzt, sollte das ~/SharePoint/-Verzeichnis von der Indexierung ausschließen, um versehentliche Dateiänderungen zu vermeiden, die upstream synchronisiert werden.
Geschrieben von Dominic Böttger
← Zurück zum Blog