Nick asked a question in the comments recently:
Now only if there was as simple a tool for setting the profile pic!
There is no simple tool, but it is not that hard really.
When an individual user wants to change their login picture, they open the Users & Groups preference pane. But if want to pre-set or change it for multiple Computers or Users, then we need to script.
Update 2019-09-20: Some of this seems to have changed since I wrote this. in 10.14.6 you will need to set the
JPEGPhoto
attribute as well. Read Alan Siu’s post for details.
Where is it stored?
The data for the user picture is stored in the user record in the directory. If the user is stored locally the directory is just a bunch of property list files in /var/db/dslocal/nodes
. However, we do not want to, nor should we manipulate them directly. The tool to interface with directory data is dscl
(directory service command line, pronounced diskel)
You can get a user’s record data like this:
$ dscl . read /Users/username
This will dump a lot of data, some of it binary. When you look more closely at the data, you can see that the binary data is in an attribute JPEGPhoto
. This is promising, but converting an image file into some binary code and writing it into the attribute does not sound fun.
When you look around the user record some more, you can find another attribute labeled Picture
which contains a decent file path (it may be empty on your machine). When JPEGPhoto
contains data, Picture
will be ignored. But when we delete the JPEGPhoto
attribute, then the system will use the file path set in the Picture
attribute.
Let’s Change It!
Deleting the JPEGPhoto
attribute is easy:
$ dscl . delete /Users/username JPEGPhoto
And so is setting the Picture
attribute to a new value:
$ dscl . create /Users/username Picture "/Library/User Pictures/Flowers/Sunflower.tif"
With this you can create a script that resets all user pictures by looping through all the available pictures in the /Library/User Pictures
folder.
(Since you are affecting other users’ records, this script needs to be run as root.)
Custom Images
Of course, you don’t have to use the pre-installed User Picture images, but can install your own.
To demonstrate how this would work, I conceived of a little fun exercise. I wanted to write a script that sets the user picture to an image from the ‘User Pictures’ folder which starts with the same letter as the username.
The set of images in the default cover 19 of the 26 letters in the latin alphabet. I created images for the seven missing letters (A, I, J, K, Q, U, and X).
To run the script at login, I created a LaunchAgent. And finally a script which will set the Picture to the appropriate path.
Since LaunchAgents run as the user, we need to be a bit more careful when changing the attributes. While a user has privileges to modify and delete the JPEGPhoto
and Picture
attribute, they cannot create the attributes, so our sledgehammer method to overwrite any existing value from the script above will not work.
The dscl . change
verb, which modifies an attribute has a weird syntax which requires you to pass the previous value as well as the new value. To get the previous value, which may contain spaces, I use the same PlistBuddy
trick from this post.
Finally, I built an installer package which installs all the parts (the additional images, the LaunchAgent plist and the script) in the right places. You can get the project here. Run the buildAlphabetUserPkg.sh
script to build an installer package.
Since the LaunchAgent will trigger at a user’s login, you will have to logout and back in, before you can see any changes. You could add a postinstall
script that loads the launchagent for the current user (when a user is logged in), but I will leave that as an exercise for the attentive student.
You can get all the pointers on how to build installer packages with postinstall
scripts in my book: “Packaging for Apple Administrators”
Thanks for the post. Any special tips for getting this working on Mojave? In testing I’m seeing the small account pic is updated (where users are listed in Users & Groups), but not the larger account icon that is displayed with user details, or at the login window.
I have actually built and tested this in Mojave. I believe you might just be running into some caching issues. Try logging out and back in to see if that updates everything.
It’s not working in 10.14.6, even with a logout and a reboot.
Wow!
Thanks for the writeup.
I put this script into Outsets’ login-privileged-once folder, and can’t seem to get it to do anything, yet the commands work when run as root in the terminal:
dscl . delete /Users/$USER JPEGPhoto
dscl . create /Users/$USER Picture “/Library/User Pictures/Fun/Logo.tif”
Not sure. Might be a PATH problem, try prefixing the dscl command with the full path, i.e. /usr/bin/dscl
https://scriptingosx.com/2018/02/setting-the-path-in-scripts/
That was 100% it. Outset has path issues. Thanks.