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
JPEGPhotoattribute 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
Let’s Change It!
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.)
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
Picture attribute, they cannot create the attributes, so our sledgehammer method to overwrite any existing value from the script above will not work.
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”