MacOS local user cleanup script

55 views
Skip to first unread message

Matt Strickland

unread,
Nov 20, 2025, 7:06:35 PM (13 days ago) Nov 20
to Techies for schools
Hi all,

Would anyone be willing to share a local user clean-up script that you might use to purge local user accounts within X inactive days? (UID >501)
I've tried to modify some scripts to use sysadminctl to delete but a little stuck on determining inactive days using accountPolicyData or suggestions from AI but coming up short.

If someone already had something they used and works, I'm still running Ventura on most of the target devices and intend to do a cleanup soon. Else ill be purging all accounts (or all leaver accounts as per usual)

Matt

Pete Mundy

unread,
Nov 20, 2025, 7:42:32 PM (13 days ago) Nov 20
to techies-f...@googlegroups.com
Heya Matt

I don't have a complete script for you, but this one liner will show you the last login for each user that has a home folder under /Users.

You could probably extend this to exclude your local admin then determine inactive days and rm -r

find /Users -maxdepth 1 -mindepth 1 -type d ! -name Shared -exec basename "{}" \; | xargs -I {} -n 1 sh -c "last {} | head -n 1"
 
Pete

--
You received this message because you are subscribed to the Google Groups "Techies for schools" group.
To unsubscribe from this group and stop receiving emails from it, send an email to techies-for-sch...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/techies-for-schools/b3ad8312-2425-435b-befc-71118a675852n%40googlegroups.com.

Dion McGovern-Allen

unread,
Nov 21, 2025, 10:59:22 PM (12 days ago) Nov 21
to Techies for schools
Hi Matt,


Essentially the same as what Pete has posted.
Configured to skip removal of our local admin account.
We run JAMF and usually the deleteAccount clears up the user.


#!/bin/sh
#Get the list of user accounts older than mtime days
users=`find /Users -type d -maxdepth 1 -mtime +14 | cut -d"/" -f3`

#Iterate through all users found, skipping admin
for i in $users; do
if [[ $i = "administrator" ]]; then continue
else
jamf deleteAccount -username $i -deleteHomeDirectory

#JAMF removal sometimes doesn't remove home directory.
chmod -Rf 777 /Users/$i
rm -Rf /Users/$i

#sysadminctl -deleteUser "$i"
fi
done


Thanks,
Dion McGovern-Allen.

Matt Strickland

unread,
Nov 23, 2025, 5:11:48 PM (10 days ago) Nov 23
to Techies for schools
Thanks Pete, Dion

I did a mash of your search tools and ai to come up with this. I'm using blanket rm -rf (no jamf here) and not using sysadminctl as that was running into issues as these are network accounts, not local users.
I assume the -maxdepth 1 will look 1 folder deep inside the users folder for a modified desktop/documents folder etc which is likely fine for my purpose. (The dry-run testing seems to reflect so)


#!/bin/bash

# ==============================================================================
# macOS User Folder Cleanup Script
# Description: Removes user home directories inactive for X days.
#              Includes an exclusion list and a safety "Dry Run" mode.
# ==============================================================================

# --- CONFIGURATION ---

# 1. Safety Switch: Set to true to seeing what WOULD happen. Set to false to delete.
DRY_RUN=true

# 2. Threshold: Number of days of inactivity
MAX_DAYS=30

# 3. Exclusion List: Add usernames/folder names you want to PROTECT.
# Always keep "Shared", "Guest", and your local admin accounts here.
EXCLUSIONS=("Shared" "Guest" "localadmin" ".localized")

# Path to Users directory
USERS_DIR="/Users"

# ==============================================================================

echo "Starting cleanup check..."
if [ "$DRY_RUN" = true ]; then
    echo "!!! DRY RUN MODE ACTIVE: No files will be deleted !!!"
fi
echo "-------------------------------------------------------"

# Get current logged in user to prevent self-deletion
CURRENT_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/kCGSSessionUserNameKey/ { print $3 }')
echo "Current active user detected as: $CURRENT_USER"

# Navigate to Users directory
cd "$USERS_DIR" || exit 1

# Loop through directories in /Users
for user_folder in */; do
    # Remove trailing slash
    user_folder=${user_folder%/}

    # Check if folder is in the exclusion list
    is_excluded=false
    for excluded in "${EXCLUSIONS[@]}"; do
        if [[ "$user_folder" == "$excluded" ]]; then
            is_excluded=true
            break
        fi
    done

    # Check if folder belongs to the currently logged-in user
    if [[ "$user_folder" == "$CURRENT_USER" ]]; then
        is_excluded=true
    fi

    if [ "$is_excluded" = true ]; then
        echo "[SKIP] $user_folder is in the exclusion list or currently active."
        continue
    fi

    # Check modification time using find logic
    # We look for the specific folder, maxdepth 0, mtime +MAX_DAYS
    if [[ $(find "$user_folder" -maxdepth 1 -mtime +$MAX_DAYS) ]]; then
       
        # Get the date the folder was last modified for logging
        mod_date=$(stat -f "%Sm" "$user_folder")
       
        if [ "$DRY_RUN" = true ]; then
            echo "[WOULD DELETE] $user_folder (Last modified: $mod_date)"
        else
            echo "[DELETING] $user_folder (Last modified: $mod_date)"
           
            # --- DELETION COMMAND ---
            # We use rm -rf for the folder.
            # Note: This deletes the data. It does not remove the user record from Directory Services
            # if they are still bound to AD/LDAP, though usually network accounts rely on the folder existence.
            rm -rf "$user_folder"
           
            if [ $? -eq 0 ]; then
                echo "Successfully removed $user_folder"
            else
                echo "Error removing $user_folder"
            fi
        fi
    else
        echo "[KEEP] $user_folder is active (modified within last $MAX_DAYS days)."
    fi
done

echo "-------------------------------------------------------"
echo "Cleanup process complete."

Dion McGovern-Allen

unread,
Nov 23, 2025, 7:16:58 PM (10 days ago) Nov 23
to Techies for schools
Hi Matt,


I just also remembered how I prepare Macbooks from TELA for staff who buy them off the scheme at the end.

As wiping them removes the Numbers/Pages/Keynote etc software from the device.
And its not "free" software - technically the first owner of the device claims the license when they first sign in with an AppleID

I reinstall the PKG downloaded from Apple Store (stripped of its owner AppleID) - you can nab the installer before it finishes installing from a temporary directory.
Then would (in single user, now recovery terminal)
Remove the .AppleSetupDone file
Remove my user home directory and remove the plist for the account. - effectively making it disappear from Users and Groups.
That plist is stored in /var/db/dslocal/nodes/Default/users/<username>.plist

However, System Integrity Protection stops you from removing the plist/s
So perhaps file it away under buying the laptop off lease.

That way they still have a copy of the free applications and go through the standard account setup.


Thanks,
Dion McGovern-Allen.
Reply all
Reply to author
Forward
0 new messages