Changing UID on Mac OS X El Capitan

I've been putting off changing my Mac UID to match that of my current employer, so that I can use an NFS mount of my work home directory. I still have the scars from the last time I had to do this. Unfortunately I left my notes on a wiki at my old employer and failed to retain a copy, so I had to figure it out all over again.

I found these notes from Roman at inteller.net to be very helpful. I decided to script the change so that I'd have it the next time I need to change my UID. The hardest bit was dealing with the spaces within filenames in the Bourne shell script. I used a bash-ism, but setting the IFS would also have worked in standard Bourne shell. 

Here's the script. You can also download it directly.

Caution: Make a backup before running the script!

Update:

The previous version of this script attempted to find and change the pathnames of files that contain the UID as part of their pathname. Phillip Law reported that the regular expression was insufficiently-strict and would match files that happen to have the UID embedded in a string of other numbers, e.g. files named with a hash or a GUID. I make a few attempts to repair this error, but it wasn't straightforward to fix it. 

Meanwhile, Phillip pointed out that it isn't necessary to update the filenames of files in places like /Library/Caches and /private/var. The system will recreate them if necessary with the correct UID in their name; it's essentially the same situation as when restoring your home directory from a backup. While the system may fail to clean up the files with the old UID in their name, at worst this should only leak a small amount of disk space.

So, I've amended the script to remove the buggy portion that attempted to find and rename files with the UID in their name.

I've also added some checks to validate the provided user name and to guard against running the script while the user is logged in.

Update 2018-02-15:

I’ve finally incorporated the bug-fix suggested in the comments below by Jean-François Beauchamp.

#! /bin/sh
# actually uses some bash extensions; see comment on line 36
# 
# change the UID of a login on Mac OS X 10.11 El Capitan
#
# run this script using sudo *from another user account*!!!
# after logging out of the account to be changed.
#
# Usage: sudo change-uid <user-name> <new UID>
# 

# sbin is in the path to pick up /usr/sbin/chown
PATH=/usr/bin:/bin:/usr/sbin:/sbin

# Two arguments: the user name and the new UID.
case $# in
	2)	USERNAME=$1 ; NEW_UID=$2 ;;
	*)	echo 'Usage: change-uid <user-name> <new UID>' 1>&2; exit 1 ;;
esac

if dscl . -ls /Users | egrep -v '_.*|com.apple.*|daemon|root|nobody' | grep $USERNAME
then
	: # USERNAME is a valid user-name
else
	echo "'$USERNAME' is not a valid user on this system" >&2
	exit 1
fi

if [ `whoami` = "$USERNAME" ]
then
	echo "You cannot run this script from the '$USERNAME' account." >&2
	echo "You must run this script from a different account." >&2
	exit 1
fi

if users | grep -q $USERNAME
then
	echo "'$USERNAME' is logged in. '$USERNAME' must be logged out to run this script." >&2
	exit 1
fi

# Obtain the current UID for the specified user.
OLD_UID=`dscl . -read /Users/$USERNAME UniqueID | cut -d ' ' -f2`

# Validate that the new UID is a string of numbers.
case $NEW_UID in
	(*[!0-9]*|'')	echo 'Error: new UID is not numeric.\nUsage: change-uid  '1>&2; exit 1 ;;
	(*)				echo "changing '$USERNAME' UID from $OLD_UID to $NEW_UID" ;;
esac

# First change ownership of the locked files.
# Otherwise, the find for the not-locked files will complain
# when it fails to change the UID of the locked files.
echo "chown uchg files in /Users/$USERNAME"
find -x /Users/$USERNAME -user $OLD_UID -flags uchg -print | while read
do
	# use bash-ism REPLY to accommodate spaces in the file name
	chflags nouchg "$REPLY"
	chown -h $NEW_UID "$REPLY"
	chflags uchg "$REPLY"
done

if [ -d /Users/Shared ]
then
	echo "chown uchg files in /Users/Shared"
	find -x /Users/Shared -user $OLD_UID -flags uchg -print | while read
	do
		chflags nouchg "$REPLY"
		chown -h $NEW_UID "$REPLY"
		chflags uchg "$REPLY"
	done
fi

# Now change ownership of the unlocked files.
echo "chown /Users/$USERNAME"
find -x /Users/$USERNAME -user $OLD_UID -print0 | xargs -0 chown -h $NEW_UID
if [ -d /Users/Shared ]
then
	echo "chown /Users/Shared"
	find -x /Users/Shared -user $OLD_UID -print0 | xargs -0 chown -h $NEW_UID
fi
echo "chown /Library"
find -x /Library -user $OLD_UID -print0 | xargs -0 chown -h $NEW_UID
echo "chown /Applications"
find -x /Applications -user $OLD_UID -print0 | xargs -0 chown -h $NEW_UID
echo "chown /usr"
find -x /usr -user $OLD_UID -print0 | xargs -0 chown -h $NEW_UID
echo "chown /private/etc"
find -x /private/etc -user $OLD_UID -print0 | xargs -0 chown -h $NEW_UID
echo "chown /private/var"
find -x /private/var -user $OLD_UID -print0 | xargs -0 chown -h $NEW_UID
echo "chown /.DocumentRevisions-V100"
find -x /.DocumentRevisions-V100 -user $OLD_UID -print0 | xargs -0 chown -h $NEW_UID
echo "chown /.MobileBackups"
find -x /.MobileBackups -user $OLD_UID -print0 | xargs -0 chown -h $NEW_UID

sync

# Finally, change the UID of the user.
echo "changing $USERNAME UniqueID to $NEW_UID"
dscl . -change /Users/$USERNAME UniqueID $OLD_UID $NEW_UID



© Steve Byan 2011-2016