Here's an easy shell script I wrote to implement multiple desktops (tested up to Sonoma). It does require root permissions to initially configure and works nicely when mapped to "hot keys" using Automator.
The only downside I've found is that you'll have to create an alias on the Finder sidebar to the folder containing the desktops, since the old "Desktop" Finder alias will only point to desktop1.
#!/bin/bash
# This Software and related documentation are provided “AS IS”
# and without any warranty of any kind and Seller EXPRESSLY
# DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT
# NOT LIMITED TO,THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR APARTICULAR #PURPOSE.
# chdt - Multiple Desktops à la X-Windows for MacOS
# Why: I needed more desktops to clutter.
# Copyright (c) 2022, 2024 by Jeff Bloomfield
# [email protected]
# Jeff Bloomfield - 2/23/2021
# REVISED 2/28/2022 hopefully fixing potential Automator hotkey mapping race
# condition when rapidly toggling between desktops.
# REVISED 11/15/2022: Damn if I know what I did. Didn't document the changes.
# Have to check backups and diff.
# Usage:
# chdt N
# where N is the desktop number or suffix
#
# Example:
# chdt 2
# Changes active desktop to the contents of $DESKTOP_DIRS/${DESKTOP_NAME}2
# Set some useful variables
PROG=$(basename $0)
DESKTOP_SYMLINK=$HOME/CurrentDesktop
DESKTOP_DIRS=$HOME/Desktops
DESKTOP_NAME=Desktop # The basename of the desktop(s), e.g., Desktop
DEBUG=0
if [ $DEBUG = 1 ]; then
ERR=/tmp/chdt_error_$LOGNAME
else
ERR=/dev/null
fi
# Setup Instructions (example):
#
# 0. Make sure the user owning the hierarchy where chdt will be configured is
# -->NOT<-- logged in to the GUI. From this point use sudo to do the
# following steps.
#
# 1. Make the directory $DESKTOP_DIRS as username in the users home directory:
#
# sudo --user=username --login mkdir Desktops
#
# 2. As root, move the user's present Desktop directory to its new home, e.g.,
#
# sudo mv ~username/Desktop ~username/Desktops/Desktop1
#
# Do the above as root because all permissions and ownership--including
# existing extended permissions are preserved ("everyone deny delete"),
# which is the OEM default). You can see extended permissions with ls -led *.
# Using mv as root keeps the directory permissions and ownership as they are.
#
# NOTE: This is ->only<- command done as root. The remaining commands
# are executed as the owner of the hierarchy where chdt is being installed.
#
# 3. As username, make the symlink $DESKTOP_SYMLINK pointing to the new location
# of your original desktop folder, e.g.,
#
# sudo --user=$USERNAME --login ln -s Desktops/Desktop1 CurrentDesktop
#
# 4. In $HOME make the symlink $HOME/Desktop:
# sudo --user=$USERNAME --login ln -s CurrentDesktop Desktop
#
# 5. Important!!! Protect the above symlink from the OS GUI turning it back into
# an empty directory (named Desktop) using chflags(1):
#
# sudo --user=$USERNAME chflags -h uchg Desktop
#
# -h acts on the symlink itself and not the directory it points to. The
# uchg flag prevents any changes to the symlink (like the OS deleteing it).
#
# NOTE: The reason for requiring a symlink pointing to a symlink is
# because chflags has Apple's undocumented "restricted" flag set,
# which disallows chflags (among other things) changing or deleting
# flags in $HOME/Desktop. [Fuck you, Apple].
#
# Check your work to see that the uchg flag is present with
#
# sudo --user=$USERNAME --login ls -Ol Desktop
# O = letter "O"
#
# 6. Have $USERNAME log in to the GUI and make empty directories for the new
# additional desktop(s) in the username's Desktops directory. Name these
# alternate desktop directories DesktopN, where N is the desktop number
# (or character(s) sequence(s)) you intend to pass in chdt's desktop
# argument (see $DESKTOP_NAME).
#
# 7. It's good practice to have the user (or you) use chmod(1) to give the
# additional desktop root directories the same extended permissions as the
# original desktop directory using chmod:
#
# chmod +a "everyone deny delete" DesktopN
# where N is the desktop number (or character sequence)
#
# See ls(1) and chmod(1) for more info on this somewhat arcane
# (and squirrelly) topic.
#
# 8. You can map chdt to hotkeys using Automator workflow (service) scripts or
# with similar third-pary software. (Automator is a squirrelly topic for
# another time.)
#
# Big Sur, Monterey Note: The OS has become more aggressive (especially on
# M-chip machines) about replacing the $HOME/Desktop symlink with an empty
# Desktop directory. So the best implementation strategy is implementing the
# changes to the Desktop symlink while the user isn't logged in to the GUI.
#
# Do the work:
#
# Get first (and only) command line argument:
DesktopNum=$1
# Catch some errors and exit with an error message:
# Warn me in case the OS has exhibited some sneaky, antisocial behavior,
# such as removing the symlink and recreating the Desktop directory or some
# other untoward behavior I don't know about yet.
if [ -e $DESKTOP_SYMNLINK] && [ ! -L $DESKTOP_SYMLINK ]; then
echo "$PROG: $DESKTOP_SYMLINK does not exist or is not symlink."\
| tee -a $ERR
exit 1
fi
if [ ! -e "${DESKTOP_DIRS}/${DESKTOP_NAME}$DesktopNum" ]; then
echo \
$PROG: ${DESKTOP_DIRS}/${DESKTOP_NAME}${DesktopNum} does not exist.\
| tee -a $ERR
exit 3
fi
if [ ! -d "${DESKTOP_DIRS}/${DESKTOP_NAME}$DesktopNum" ]; then
echo \
$PROG: ${DESKTOP_DIRS}/${DESKTOP_NAME}${DesktopNum} is not a directory.\
| tee -a $ERR
exit 4
fi
# Silently ignore attempts to chdt to the current desktop
if \
[ $(readlink $DESKTOP_SYMLINK) = $DESKTOP_DIRS/$DESKTOP_NAME${DesktopNum} ]
then
exit 0 # Not an error; just do nothing and exit with no error (exit 0)
# Otherwise automator throws an error if exit() is non-zero.
fi
# Remake $DESKTOP_SYMLINK to point to the new desktop
if ! /bin/ln -hfs $DESKTOP_DIRS/$DESKTOP_NAME${DesktopNum} $DESKTOP_SYMLINK
then
echo "$PROG: ln -hfs failed to create symlink
$DESKTOP_DIRS/$DESKTOP_NAME${DesktopNum} -> $DESKTOP_SYMLINK" \
| tee -a $ERR
exit 5
fi
if ! pkill -U $(id -u) '^Finder$'; then
echo "Failed to restart finder for some unknown reason (so sue me)."
exit 6
fi
exit 0