Backup and restore your desktop icon layout on Cinnamon/Nemo and XFCE.
Cinnamon and XFCE backups are kept completely separate, and no attempt is made
to translate icon positions between the two environments. The script can also
recover missing ~/Desktop items from the matching environment's snapshot.
Save the script below as Linux_desktopicons.sh and make it executable:
chmod +x Linux_desktopicons.sh
Run this while logged into the desktop you want to capture. It auto-detects Cinnamon vs. XFCE:
./Linux_desktopicons.sh backup
Run this after icons get scrambled (e.g. a monitor change or a login glitch). It also auto-detects the current desktop:
./Linux_desktopicons.sh restore
Running the script with no argument is the same as restore.
If auto-detection fails, or you want to target a specific environment, use the explicit commands:
./Linux_desktopicons.sh backup-cinnamon
./Linux_desktopicons.sh restore-cinnamon
./Linux_desktopicons.sh backup-xfce
./Linux_desktopicons.sh restore-xfce
The backup root defaults to /media/$USER/storage/LinuxSaved/backup/DesktopIcons
(derived from the logged-in user, not a hardcoded name). Override it by setting
the DESKTOP_ICONS_BACKUP_DIR environment variable, e.g.:
DESKTOP_ICONS_BACKUP_DIR="$HOME/backups/DesktopIcons" ./Linux_desktopicons.sh backup
| Environment | Backup location |
|---|---|
| Cinnamon / Nemo | <backup-root>/cinnamon_nemo |
| XFCE | <backup-root>/xfce |
Each backup captures icon positions, the relevant desktop settings, and a full
snapshot of ~/Desktop so missing items can be recovered on restore.
#!/bin/bash
#desc: restores the icon locations in cinnamon or xfce
# Backup and restore desktop icon layout + basic desktop item recovery for:
# - Cinnamon (Nemo managing desktop)
# - XFCE (xfdesktop managing desktop)
#
# Goals:
# 1) Keep Cinnamon/Nemo and XFCE backups completely separate.
# 2) Do NOT translate icon positions between environments.
# 3) Optionally recover missing ~/Desktop items from the matching environment backup.
set -euo pipefail
DESKTOP_DIR="$HOME/Desktop"
# Backup root. Override with DESKTOP_ICONS_BACKUP_DIR; otherwise derive from the
# current user rather than hardcoding a username.
BASE_BACKUP_DIR="${DESKTOP_ICONS_BACKUP_DIR:-/media/$USER/storage/LinuxSaved/backup/DesktopIcons}"
NEMO_BACKUP_DIR="$BASE_BACKUP_DIR/cinnamon_nemo"
XFCE_BACKUP_DIR="$BASE_BACKUP_DIR/xfce"
# Cinnamon/Nemo artifacts
NEMO_ICONS_FILE="$NEMO_BACKUP_DIR/icons.backup"
NEMO_DESKTOP_DCONF="$NEMO_BACKUP_DIR/org.nemo.desktop.backup"
NEMO_ICONVIEW_DCONF="$NEMO_BACKUP_DIR/org.nemo.icon-view.backup"
NEMO_DESKTOP_METADATA="$NEMO_BACKUP_DIR/desktop-metadata.backup"
# XFCE artifacts
XFCE_DESKTOP_DIR="$HOME/.config/xfce4/desktop"
XFCE_XML_DIR="$HOME/.config/xfce4/xfconf/xfce-perchannel-xml"
XFCE_XML_FILE="xfce4-desktop.xml"
log() { printf "%s\n" "$*"; }
ensure_dir() {
local d="$1"
[ -d "$d" ] || mkdir -p "$d"
}
command_exists() { command -v "$1" >/dev/null 2>&1; }
detect_desktop() {
# Prefer environment variables; fall back to running processes.
# Returns: "cinnamon" or "xfce"
local xdg="${XDG_CURRENT_DESKTOP:-}"
local session="${DESKTOP_SESSION:-}"
local gdm="${GDMSESSION:-}"
local probe
probe="$(printf '%s
%s
%s
' "$xdg" "$session" "$gdm" | tr '[:upper:]' '[:lower:]')"
if printf '%s' "$probe" | grep -q 'cinnamon'; then
printf '%s
' "cinnamon"
return 0
fi
if printf '%s' "$probe" | grep -q 'xfce'; then
printf '%s
' "xfce"
return 0
fi
# Process-based fallback
if pgrep -x xfdesktop >/dev/null 2>&1; then
printf '%s
' "xfce"
return 0
fi
if pgrep -x nemo-desktop >/dev/null 2>&1; then
printf '%s
' "cinnamon"
return 0
fi
if pgrep -x cinnamon >/dev/null 2>&1; then
printf '%s
' "cinnamon"
return 0
fi
return 1
}
backup_current() {
local de
if ! de="$(detect_desktop)"; then
echo "Error: Unable to detect current desktop environment (expected Cinnamon or XFCE)." >&2
echo "Hint: run with an explicit command (backup-cinnamon / backup-xfce)." >&2
exit 2
fi
case "$de" in
cinnamon) backup_nemo ;;
xfce) backup_xfce ;;
*)
echo "Error: Unsupported detected desktop environment: $de" >&2
exit 2
;;
esac
}
restore_current() {
local de
if ! de="$(detect_desktop)"; then
echo "Error: Unable to detect current desktop environment (expected Cinnamon or XFCE)." >&2
echo "Hint: run with an explicit command (restore-cinnamon / restore-xfce)." >&2
exit 2
fi
case "$de" in
cinnamon) restore_nemo ;;
xfce) restore_xfce ;;
*)
echo "Error: Unsupported detected desktop environment: $de" >&2
exit 2
;;
esac
}
backup_desktop_items() {
# Full snapshot of ~/Desktop for best-effort recovery within the same environment.
local target_dir="$1/desktop-items"
ensure_dir "$1"
rm -rf "$target_dir"
ensure_dir "$target_dir"
if [ -d "$DESKTOP_DIR" ]; then
if command_exists rsync; then
# Preserve permissions, symlinks, times; omit device/special files.
rsync -a --delete --exclude '.Trash*' "$DESKTOP_DIR"/ "$target_dir"/
else
# Fallback: copy everything (including hidden), best-effort.
( shopt -s dotglob nullglob
cp -a "$DESKTOP_DIR"/* "$target_dir"/ 2>/dev/null || true
)
fi
fi
}
restore_missing_desktop_items() {
local source_dir="$1/desktop-items"
if [ ! -d "$source_dir" ]; then
log "Note: No desktop-items snapshot found at: $source_dir"
return 0
fi
ensure_dir "$DESKTOP_DIR"
( shopt -s dotglob nullglob
for item in "$source_dir"/*; do
[ -e "$item" ] || continue
local name
name="$(basename "$item")"
if [ ! -e "$DESKTOP_DIR/$name" ]; then
log "Recovering missing Desktop item: $name"
cp -a "$item" "$DESKTOP_DIR/$name" 2>/dev/null || true
fi
done
)
}
############################################
# Cinnamon / Nemo
############################################
backup_nemo() {
ensure_dir "$NEMO_BACKUP_DIR"
: > "$NEMO_ICONS_FILE"
# Include hidden files; exclude '.' and '..'
( shopt -s dotglob nullglob
for file in "$DESKTOP_DIR"/*; do
[ -e "$file" ] || continue
local filename gio_output position
filename="$(basename "$file")"
# Nemo stores icon coordinates as gio metadata
gio_output="$(gio info "$file" 2>/dev/null || true)"
position="$(printf "%s\n" "$gio_output" | grep -F "metadata::nemo-icon-position:" | awk '{print $2}' || true)"
if [ -n "${position:-}" ]; then
printf "%s:%s\n" "$filename" "$position" >> "$NEMO_ICONS_FILE"
fi
done
)
# Save Nemo desktop settings
dconf dump /org/nemo/desktop/ > "$NEMO_DESKTOP_DCONF" || true
dconf dump /org/nemo/icon-view/ > "$NEMO_ICONVIEW_DCONF" || true
# Save Nemo desktop-metadata file (if present)
if [ -f "$HOME/.config/nemo/desktop-metadata" ]; then
cp -f -p "$HOME/.config/nemo/desktop-metadata" "$NEMO_DESKTOP_METADATA"
fi
# Snapshot the Desktop contents for recovery
backup_desktop_items "$NEMO_BACKUP_DIR"
log "Cinnamon/Nemo backup complete:"
log " $NEMO_BACKUP_DIR"
}
restore_nemo() {
if [ ! -f "$NEMO_DESKTOP_DCONF" ] || [ ! -f "$NEMO_ICONVIEW_DCONF" ]; then
log "Error: Nemo dconf backups not found in: $NEMO_BACKUP_DIR"
exit 1
fi
# Restore desktop items (best-effort)
restore_missing_desktop_items "$NEMO_BACKUP_DIR"
# Restore Nemo settings
dconf load /org/nemo/desktop/ < "$NEMO_DESKTOP_DCONF" || true
dconf load /org/nemo/icon-view/ < "$NEMO_ICONVIEW_DCONF" || true
# Restore desktop-metadata (if present)
if [ -f "$NEMO_DESKTOP_METADATA" ]; then
ensure_dir "$HOME/.config/nemo"
cp -f -p "$NEMO_DESKTOP_METADATA" "$HOME/.config/nemo/desktop-metadata"
fi
# Restore icon positions (only if we have them)
if [ -f "$NEMO_ICONS_FILE" ]; then
while IFS=: read -r filename position; do
[ -n "${filename:-}" ] || continue
[ -n "${position:-}" ] || continue
local filepath="$DESKTOP_DIR/$filename"
if [ -e "$filepath" ]; then
gio set "$filepath" metadata::nemo-icon-position "$position" >/dev/null 2>&1 || true
fi
done < "$NEMO_ICONS_FILE"
fi
# Restart nemo-desktop to apply changes
if pgrep -x nemo-desktop >/dev/null 2>&1; then
killall nemo-desktop >/dev/null 2>&1 || true
fi
nohup nemo-desktop >/dev/null 2>&1 & disown || true
log "Cinnamon/Nemo restore complete."
}
############################################
# XFCE / xfdesktop
############################################
backup_xfce() {
ensure_dir "$XFCE_BACKUP_DIR"
# Save xfdesktop icon layout files (multi-monitor friendly)
if [ -d "$XFCE_DESKTOP_DIR" ]; then
ensure_dir "$XFCE_BACKUP_DIR/xfce-desktop"
cp -a "$XFCE_DESKTOP_DIR"/icons.screen*.rc "$XFCE_BACKUP_DIR/xfce-desktop/" 2>/dev/null || true
fi
# Save main desktop config (contains icon settings among other things)
if [ -f "$XFCE_XML_DIR/$XFCE_XML_FILE" ]; then
ensure_dir "$XFCE_BACKUP_DIR/xfconf"
cp -a "$XFCE_XML_DIR/$XFCE_XML_FILE" "$XFCE_BACKUP_DIR/xfconf/$XFCE_XML_FILE" 2>/dev/null || true
fi
# Snapshot the Desktop contents for recovery
backup_desktop_items "$XFCE_BACKUP_DIR"
log "XFCE backup complete:"
log " $XFCE_BACKUP_DIR"
}
restore_xfce() {
# Restore desktop items (best-effort)
restore_missing_desktop_items "$XFCE_BACKUP_DIR"
# Restore layout files
if [ -d "$XFCE_BACKUP_DIR/xfce-desktop" ]; then
ensure_dir "$XFCE_DESKTOP_DIR"
cp -a "$XFCE_BACKUP_DIR/xfce-desktop"/icons.screen*.rc "$XFCE_DESKTOP_DIR/" 2>/dev/null || true
fi
# Restore main config file
if [ -f "$XFCE_BACKUP_DIR/xfconf/$XFCE_XML_FILE" ]; then
ensure_dir "$XFCE_XML_DIR"
cp -a "$XFCE_BACKUP_DIR/xfconf/$XFCE_XML_FILE" "$XFCE_XML_DIR/$XFCE_XML_FILE" 2>/dev/null || true
fi
# Reload xfdesktop (preferred) or restart it
if command_exists xfdesktop; then
xfdesktop --reload >/dev/null 2>&1 || true
fi
if pgrep -x xfdesktop >/dev/null 2>&1; then
pkill xfdesktop >/dev/null 2>&1 || true
fi
nohup xfdesktop >/dev/null 2>&1 & disown || true
log "XFCE restore complete."
}
usage() {
cat <<'USAGE'
Usage:
desktopicons_with_restore.sh backup
desktopicons_with_restore.sh restore
desktopicons_with_restore.sh backup-current
desktopicons_with_restore.sh restore-current
desktopicons_with_restore.sh backup-cinnamon
desktopicons_with_restore.sh restore-cinnamon
desktopicons_with_restore.sh backup-xfce
desktopicons_with_restore.sh restore-xfce
Notes:
- 'backup'/'restore' automatically detect your current desktop (Cinnamon vs XFCE).
- Backup root defaults to /media/$USER/storage/LinuxSaved/backup/DesktopIcons
(override with the DESKTOP_ICONS_BACKUP_DIR environment variable).
- Cinnamon backups are stored under: <backup-root>/cinnamon_nemo
- XFCE backups are stored under: <backup-root>/xfce
- Restores are environment-specific; no cross-desktop translation is attempted.
USAGE
}
case "${1:-}" in
"") restore_current ;;
backup|backup-current) backup_current ;;
restore|restore-current) restore_current ;;
backup-cinnamon) backup_nemo ;;
restore-cinnamon) restore_nemo ;;
backup-xfce) backup_xfce ;;
restore-xfce) restore_xfce ;;
-h|--help|help) usage; exit 0 ;;
*)
echo "Error: Invalid argument: $1" >&2
usage
exit 1
;;
esac