Delete All Users except local admin

jshipman
New Contributor III

I currently have mobile accounts on all of my student computers. I know, I know I could change them to strictly network accounts, but sometimes it's convenient for them to be able to save to the desktop and the teachers freak out a little less. Anyhoo, I'd like to be able to delete all users except for the local admin as a sort of summer clean up. Any scripts out there that would delete all users, not just one at log out?

Thanks!

9 REPLIES 9

franton
Valued Contributor III

This is the script we use. It's coded to look for a file that sits on our domain controller SYSVOL folder and then exempt users listed in it from deletion. It's probably overkill for your needs but it'll be a good starting point. It's got some horrible kludges in it to cope with the fact our localadmin txt file is edited by Windows users. (Unix and Windows deal with carriage returns in different ways).

#!/bin/bash

# Clear all non local admin accounts script
# Script is based off work at the following webpage:
# http://www.macos.utah.edu/documentation/authentication/dscl.html

# Author: r.purves@arts.ac.uk

# Set up needed variables here

macname=$( scutil --get ComputerName | awk '{print substr($0,length($0)-3,4)}' )
OIFS=$IFS
IFS=$'
'

# Special section to set up globally exempted user accounts
# You can add more accounts here separated by a space

exempt=( admin Shared Guest .localized )

# Mount fileshare where local admin file is kept.

mkdir /Volumes/SYSVOL
mount_smbfs -o nobrowse //'DOMAIN;account:password'@domain.local/SYSVOL /Volumes/SYSVOL

# Read localadmin file to LOCADMIN variable. We'll do all our processing from that.

LOCADMIN=$( cat /Volumes/SYSVOL/domain.local/localadmin/localadmins.txt)

# Unmount and clean up fileshare.

diskutil umount force /Volumes/SYSVOL

while read -r LOCADMIN
do

# Because the file contains bash reserved characters, we must remove them before processing.
# This will cause the script to ignore the line totally.

   line=$( echo ${LOCADMIN//[*]/} )

# Grab the name of the computer from the current line of the file

   compname=$( echo "${line}" | cut -d : -f 1 | awk '{print substr($0,length($0)-3,4)}' )

# Find out how many users are listed by counting the commas

   usercount=$( echo $((`echo ${line} | sed 's/[^,]//g' | wc -m`-1)) )

# Does the current computer name match the one in the file?

   if [ "$macname" = "$compname" ];
   then

      for (( loop=0; loop<=usercount; loop++ ))
      do

         field=$(($loop + 1))
         username=$( echo "${line}" | cut -d : -f 4 | cut -d "," -f ${field} | cut -c11- | sed "s/$(printf '
')$//" )

      done             
   fi

done << EOF
$LOCADMIN
EOF

exempt[$[${#exempt[@]}]]=`echo $username`

# Find exempt array length

tLen=${#exempt[@]}

# Delete accounts apart from those in the exclusion array

# Read the user account from /users in order.

for Account in `ls /Users`
do

# Does the flag file exist? If so, delete it.

   if [ -f /var/tmp/adminexempt ];
   then
      rm /var/tmp/adminexempt
   fi

# Loop around the exemption array to check current user.

   for (( i=0; i<${tLen}; i++ ));
   do

# Create the exemption flag file if account matches. We do this because of BASH's local variable limitation.

      if [ "${exempt*}" == $Account ];
      then
         touch /var/tmp/adminexempt
      fi

   done

# If exempt file doesn't exist, delete the account.

   if [ ! -f /var/tmp/adminexempt ];
   then
      dscl . delete /Users/$Account > /dev/null 2>&1
      rm -rf /Users/$Account
   fi

# Read the next username.

done

# Let's set IFS back to the way it was.

export IFS=$OIFS

# Clean up any left over flag files

if [ -f /var/tmp/adminexempt ];
then
   rm /var/tmp/adminexempt
fi

# All done!

exit 0

imperatives
New Contributor III

I cannot recall who posted this script, but it has worked well for me. This example will delete mobile accounts (they have UniqueID's greater than 1000), but not local accounts on machines that older than 7 days. Just set the "-mtime +7" to the number of days old an account must be on the machines before it is deleted. You could customize it to delete non-admin local accounts as well.

#!/bin/sh
userList=dscl . list /Users UniqueID | awk '$2 > 1000 {print $1}'
echo "Deleting account and home directory for the following users..."
for a in $userList ; do
find /Users -type d -maxdepth 1 -mindepth 1 -not -name "." -mtime +7 | grep "$a";
if [[ $? == 0 ]]; then
dscl . delete /Users/"$a"; #delete the account
rm -r /Users/"$a"; #delete the home directory
fi
done

JAMAUAI
New Contributor II

I know this is an old post, but I had the same question several nights ago, this command worked for me just fine:

sudo find /Users/* -type d -maxdepth 0 ! -name admin -exec rm -rf {} ;

Oh and hi Jessie! (:

Moustapha
New Contributor

Work ! great ...and ...i wish to delete for example except another users ....for example, i want to delete

Users/* ==== all ====ok, except, admin and usertemplate ( 2 users in except )....

What is good syntax ??
Thanks ..

allanp81
Valued Contributor

Try this:

#!/bin/bash
#This Script will remove all accounts that are not
#specified below (e.g. Administrator, etc.)
#Accounts are case sensitive

UserList=`ls /Users | grep -v "Shared" | grep -v -i "admin" | grep -v -i ".localized" | grep -v -i "kingston" | grep -v -i "administrator" | grep -v -i "arduser"`

Dansarray=( $UserList )
#printf "%s
" "${Dansarray[@]}"

if [ ${#Dansarray[@]} -eq 0 ]; 
    then
        echo "Nothing to do, exiting"
        exit 0
    else
        for u in ${Dansarray[@]} ; do
            echo "$u -- Deleting..."
            `/usr/bin/dscl . delete /Users/$u && /bin/rm -rf /Users/$u`
        done
        #Remove sharepoints and groups
        find /private/var/db/dslocal/nodes/Default/sharepoints -name "*" -type f -delete
        find /private/var/db/dslocal/nodes/Default/groups -name "com.apple.sharepoint*" -type f -delete
fi

Moustapha
New Contributor

No script just command shell :

sudo find /Users/* -type d -maxdepth 0 ! -name admin -exec rm -rf {} ; for one user ====> admin -----OK

For two users? example = admin and usertemplate?

Thanks ...

nigelg
Contributor

@allanp81 I had an interesting experience with that script. A package I installed created a root folder in /Users/. Without any error checking, my root account was deleted from the directory service and bad things happened :)

Might be worth adding something like this to the exclusions :-

grep -v "root"

So its :-

#!/bin/bash
#This Script will remove all accounts that are not
#specified below (e.g. Administrator, etc.)
#Accounts are case sensitive

UserList=`ls /Users | grep -v "Shared" | grep -v -i "admin" | grep -v -i "root" | grep -v -i ".localized" | grep -v -i "kingston" | grep -v -i "administrator" | grep -v -i "arduser"`

Dansarray=( $UserList )
#printf "%s
" "${Dansarray[@]}"

if [ ${#Dansarray[@]} -eq 0 ]; 
    then
        echo "Nothing to do, exiting"
        exit 0
    else
        for u in ${Dansarray[@]} ; do
            echo "$u -- Deleting..."
            `/usr/bin/dscl . delete /Users/$u && /bin/rm -rf /Users/$u`
        done
        #Remove sharepoints and groups
        find /private/var/db/dslocal/nodes/Default/sharepoints -name "*" -type f -delete
        find /private/var/db/dslocal/nodes/Default/groups -name "com.apple.sharepoint*" -type f -delete
fi

allanp81
Valued Contributor

@nigelg that's odd for a package to install into /Users/root? What package was it? We've been using that script for years now without any issues.

nigelg
Contributor

@allanp81 I think it was a package manually created by an admin who was having an off-day :)