How to change local user account Picture through command terminal

norett
New Contributor

hi there,

I currently want to change my local admin account's picture through command for about 50 macs.

I tried many things, and the command below seems to work but not all the time, wonder why...?

In Terminal :

su #my admin username...)
password #enter your password

dscl . -append "/Users/admin" picture "/Library/User Pictures/Animals/Cat.tif"

where admin is the local account you want to change the picture of and cat.tif the new picture.

It seemed to work on 10.6.8, do you have any other clues on how to change the picture with a script ?

I tried apple script but it does not work !

thanks a lot

45 REPLIES 45

kevindigg
New Contributor

Do all the admin accounts have the same picture? If so, you could first run the following to get the path of the account picture:

dscl . -read /Users/admin Picture

Which will return (for example):
Picture: /Library/User Pictures/Sports/Soccer.tif

using your cat.tif example as the new picture, you can then run:

sudo dscl . -change /Users/admin Picture '/Library/User Pictures/Sports/Soccer.tif' '/Library/User Pictures/Animals/Cat.tif'

Where the first argument after Picture is the path to the current picture and the second argument the path to the new picture. Then, as long as the image is on all the computers, you could push out that command via a script or policy.

At least, I think it should work.

stevewood
Honored Contributor II
Honored Contributor II

I posted an answer for your response yesterday on the other thread you commented on:

https://jamfnation.jamfsoftware.com/discussion.html?id=3206

norett
New Contributor

hi, thanks for the help.

i want to change the admin account profile pictures of some computer. I'll just have all the pictures I need on my master to do that. but do i need to do this command from an admin ? the users will be logged in on my active directory...

the script below deleted the picture but did not put the new picture. does it work with .jpg or .tiff ou .jpeg ?

thanks a lot !

stevewood
Honored Contributor II
Honored Contributor II

I answered your question on the other thread about why you were unable to get your picture to work. It had to do with you not running the script using "sudo" since you were running from the terminal.

As to your post here, I have a package that I push to machines from Casper. That package drops the user picture into /Library/User Pictures/Integer. I can target that at specific machines if I want to. After installing that package, then I run the commands to change the picture for the admin user. And again, I do that with a script pushed from Casper, so the script runs as root. If you want to run it from the terminal by hand, you have to use sudo.

HTH

norett
New Contributor

We'll talk here :)
Thanks !

The thing is even doing that it does not work, and even as root... with a jpg it doesn't work either... and do I need to reboot or logout to see the changes . the images is deleted, i see the blue apple logo but not mine! and if I select an image from the macs users library it still doesn't work :(

how do you create this script to be run as root and create a policy if possible ?

thanks for your help

stevewood
Honored Contributor II
Honored Contributor II

Okay, first up, why it isn't working (from the other thread). If you look at the last line of the commands:

sudo dscl . create /Users/admin Picture "/wunderman.tif"

You are telling dscl to use the image at the root of your hard drive ("/wunderman.tif"). If you want to use the image from the User Pictures folder that you placed there, the final command should look like this:

sudo dscl . create /Users/admin Picture "/Library/User Pictures/wunderman.tif"

Try that.

To your other question:

how do you create this script to be run as root and create a policy if possible ?

You would put the commands into a shell script file and upload that file to Casper via Casper Admin. Set the script to run as an At Reboot script (if you are wanting to do this during imaging, or as an After script if you want to run at any time. If all you want to do is change the picture, your script can be as simple as:

#!/bin/sh

dscl . delete /Users/admin jpegphoto
dscl . delete /Users/admin Picture
dscl . create /Users/admin Picture "/Library/User Pictures/wunderman.tif"

exit 0

Once uploaded to Casper, in the JSS you would create a policy and choose the script to run. If you need assistance creating the policy, refer to page 321 in the Casper Suite 8.5 Administrator's Guide.

And, to get better at scripting, I would highly suggest, as many others would, picking up a copy of O'Reilly's "Learning the Bash Shell" book:

http://www.amazon.com/Learning-bash-Shell-Programming-Nutshell/dp/0596009658/ref=sr_1_1?ie=UTF8&qid=...

Or there are plenty of other resources on the web for learning Bash.

HTH

norett
New Contributor

hi,

My script WORKS !

thanks a lot,

now I'll try to get the images of my AD users from a file server in my script,

i'll let you know if I get it to work,

thanks again

stevewood
Honored Contributor II
Honored Contributor II

Can you post the contents of your script?

cjducasse
New Contributor

This has all been very helpful. I'm beginning to get to the root of our problem. Our issue is we would like to reset the account picture on a particular group of computers.
We have tried the following commands as root through ARD and locally, everything appears to work, but we don't actually see the changes made, even after reboot

sudo dscl . -append '/Users/d46student' Picture '/Library/User Pictures/Fun/Gingerbread Man.tif'
sudo dscl . -change /Users/d46student Picture '/Library/User Pictures/Nature/Earth.tif' '/Library/User Pictures/Fun/Gingerbread Man.tif'

If it makes any difference, the computers are all on 10.7.5

tkimpton
Valued Contributor II

anyone got a script that works for this please? Not working 10.8.4

chris_kemp
Contributor III

Just for fun, started going over this stuff...

So the dscl command does seem to pull & add "legitimate" values...but that's not what the user picture is being derived from, at least not initially.

According to dscl, mine was "Smack.tif" (which I have not been seeing...not sure WHEN that was set!) - my login picture, however, was the lightning bolts. (These are all standard Apple choices, not stuff I've added). So, I changed it in System Preferences -> Users to the jazz guitar image...and the dscl key was suddenly gone... :-/

Then, I used dscl to set it to Ying Yang.tif - the key took, but the picture did not change. I even switched to the login window & back, but it still had the jazz guitar image. hmm...

Next, I did some research & found that "recent" pictures are being stored in ~/Library/Containers/com.apple.ImageKit.RecentPictureService/Data/Library/Images/Recent Pictures - looking here, I found a bunch of cryptic file names, such as A3D57D81-59FA-442F-A1F6-CA0405D09DE8-thumbnail.tiff - which turned out to be the jazz guitar picture! Right below that one was the lightning bolts - aha! I confirmed this by running 'open *" in Terminal, which of course opened every file in the directory. I did not see the Ying Yang.tif, however...until...

I went back to System Preferences/Users to change pictures again...and suddenly I have Ying Yang as my profile picture. =8-0

So anyway...there's something else going on here besides dscl alone.

chris_kemp
Contributor III

Continued...

Changed the picture a couple more times using dscl - and the picture updates by going to the login window and back. However, opening up System Preferences -> Users & Groups again, the Ying Yang is still there. If I change it here, the dscl key is deleted and the picture updates immediately, i.e. no login window round-trip needed.

And again, setting a picture via dscl again has no immediate effect...and I can't seem to get it to update again, no idea how that happened the last time?

Very strange...

ToriAnneke
Contributor II

Hi all,

I've been trying to do this for some time...

From what I've been noticing, seems that the absolute path of the Picture in the user's plist has been replaced to a HEX value.

So, if I run in Terminal

dscl . -read /Users/me Picture

Terminal kicks back

No such Key

but if i do

dscl . -read /Users/me jpegphoto

Terminal kicks back

the HEX of the photo

I changed from within System Pref the photo from the built in Butterfly to the Baseball and sure enough, the hex changes.
Compared the HEX output using HexEdit.app and sure enough I was right.

So I think it's a matter of converting the photo that you want to use into HEX and then replacing the

jpegphoto
Key in the targeted plist.

But I'm afraid of HEX :)

kevindigg
New Contributor

I can't take credit for coming up with this, but I've used it successfully in the past to convert the hex to a jpeg:

dscl . -read /Users/username JPEGPhoto | tail -1 | xxd -r -p > /path/to/save/whatever.jpg

quedayone
Contributor

Just checking to see if anyone has this working on 10.9?

joshuasee
Contributor III

Unfortunately, dscl cannot write binary values, so there is no way to set a picture using it. dsimport can, so:

#!/bin/bash
echo "0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 4 dsAttrTypeStandard:RecordName dsAttrTypeStandard:UniqueID dsAttrTypeStandard:GeneratedUID externalbinary:dsAttrTypeStandard:JPEGPhoto" > import.txt
echo $USER:$UID:$(id -g):$(dscl . -read /Users/$USER GeneratedUID | cut -d' ' -f2):/path/to/user_picture.jpg >> import.txt
dscl . -delete /Users/$USER JPEGPhoto
dsimport /path/to/import.txt /Local/Default M -u diradmin
rm import.txt

The script creates a file formatted for dsimport based on existing account data and with a pointer to a user picture, which must be in JPEG format, and then deletes the existing user picture, if any, and merges the import file with the existing account. dsimport handles encoding the JPEG and copying it into the account record.

stevewood
Honored Contributor II
Honored Contributor II

I just tested this on my machine running 10.9, and I'm still able to use my original method of changing the user icon:

#!/bin/sh

dscl . delete /Users/admin jpegphoto
dscl . delete /Users/admin Picture
dscl . create /Users/admin Picture "/Library/User Pictures/wunderman.tif"

exit 0

If you want to use a different picture, just make sure the picture is on the system and point that last dscl line to that location.

zanb
New Contributor III

Hey all. Thought I'd contribute to this thread since I figured out how to do this.

# # Reboot is highly encouraged # #

#!/bin/bash
# Delete the hex entry for jpegphoto
dscl . delete /Users/USER jpegphoto
dscl . delete /Users/USER Picture
dscl . create /Users/USER Picture "/Library/User Pictures/Fun/Chalk.tif"
#  This forces the system to rebuild the system caches 
#+ along with the local directory cache.
kextcache -system-caches
exit

This is known to work on 10.8 and 10.9. I haven't tested it on 10.7.

tkimpton
Valued Contributor II

anyone had any luck on 10.10.2?

Can't seem to get this working on the filevault 2 screen

Thanks

toj
New Contributor

I've got the same issue with @tkimpton. This works great for getting the icon set everywhere except for the FileVault 2 login screen.

The only way I've been able to get it set there is by going to System Preferences, changing the icon to something else, then changing it back. It's got to be doing something else when setting the user icon in System Preferences, but what?

gregneagle
Valued Contributor

It's rebuilding a bunch of files used in the EFI pre-boot environment.

When FileVault 2 is active and you power on the machine, when you see the screen that shows user icons: the machine is NOT RUNNING OS X at that point. The boot volume is still encrypted! The machine is running the EFI boot loader.

You can get OS X to rebuild the files used by EFI to display the user picture, etc like so:

sudo touch /System/Library/PrivateFrameworks/EFILogin.framework/Resources/EFIResourceBuilder.bundle/Contents/Resources

It's an odd thing; one would expect an actual command to run, but it seems to work.

tkimpton
Valued Contributor II

unfortunately this still doesn't work on fv2 screen on 10.10.2

has anyone got this working please?

marklamont
Contributor III

has anyone got this to work on 10.12? All I can manage to do is end up with this situation89ecf45ada6e42e691a7348427540257

quedayone
Contributor

Just tested this code and it seems to work.
https://github.com/quedayone/jamf-pro-scripts/blob/master/user-picture-change
Can anyone confirm?

kquan
Contributor

@quedayone thanks for finding that! I just tested that and it works!

quedayone
Contributor

@kquan Sweet!

zanb
New Contributor III

@quedayone link has 404'd. Can you repost the code, perhaps?

jhbush
Valued Contributor II

zanb
New Contributor III

Oh, I see. The URL has a "<br>" in the original link. Thanks.

brian_mccarthy1
New Contributor II

When I run @jhbush1973 script, I get the following error:

DS Error: -14120 (eDSPermissionError)

Not sure why. its able to find the picture.

jduvalmtb
Contributor

@brian_mccarthy Did you run as root? I got the same error without sudoing.

Using a school logo, this script still gives the screenshot for me that @marklamont posted, but it at least displays correctly at the login screen.

Regardless, I also ran into the issue of our custom school logo not appearing on the login screen using dscl. I ended up replacing a built-in User Picture (eg, fun/Medal.tif) with our school logo and used dscl to use that picture and it shows up correctly at login. Simply using dscl to add the school logo (schoolLogo.tif) and the login logo is blank. No idea why.

RandyTanenhaus
New Contributor II

Using the above Jamf Pro Script of user-picture-change, anyone know why I am getting the following error in the script?

Script result: <br/>Checking for: /Library/User Pictures/Compass.jpg . . .<br/><br/>found: /Library/User Pictures/Compass.jpg<br/><br/>Changeing user icon to: /Library/User Pictures/Compass.jpg<br/>sudo: dscl: command not found<br/>sudo: dscl: command not found<br/><br/>testuser Current user picture is:<br/>/Library/User Pictures/Compass.jpg<br/>

Specifically the "sudo: dscl: command not found<br/>sudo: dscl: command not found" part? It finds the current user fine, but can't run dscl?

Got to be something simple I am missing, but I haven't found it yet.

tech-otaku
New Contributor II

Here in 2018 running macOS 10.13.3 and the solution posted in this thread by @joshuasee way back in 2014 is the only one that comes close to working. On the first line I had to add dsAttrTypeStandard:PrimaryGroupID after dsAttrTypeStandard:UniqueID and on the same line changed Users 4 to Users 5.

#!/bin/bash
echo "0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 5 dsAttrTypeStandard:RecordName dsAttrTypeStandard:UniqueID dsAttrTypeStandard:PrimaryGroupID dsAttrTypeStandard:GeneratedUID externalbinary:dsAttrTypeStandard:JPEGPhoto" > import.txt
echo $USER:$UID:$(id -g):$(dscl . -read /Users/$USER GeneratedUID | cut -d' ' -f2):/path/to/user_picture.jpg >> import.txt
dscl . -delete /Users/$USER JPEGPhoto
dsimport /path/to/import.txt /Local/Default M -u diradmin
rm import.txt

On line 4 remember to change diradmin to a valid admin user name on your system.

NOTE: When run as sudo the script didn't set/change the user picture. Run the script as an admin user then wait for dsimport to prompt you for the password.

msw
Contributor

@tech-otaku Would you be able to provide a bit more info about how to use this script? I'm not quite following how I would use this to change the settings for a particular user. Do I need to define $USER and $UID? Also, is your note at the end saying that this script will send a manual password prompt? I'm looking for something to be triggered by a policy.

My specific use case is setting the profile picture for the secondary admin user created automatically by the pre-stage enrollment settings.

Edit: did some testing and got this working. My script looks like this:

#!/bin/bash

# Script to set the profile picture for user X to picture Y
# via https://www.jamf.com/jamf-nation/discussions/4332/how-to-change-local-user-account-picture-through-command-terminal#responseChild162438

USER="user_you_want_to_update"
UID="user_uid_you_want_to_update"

echo "0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 5 dsAttrTypeStandard:RecordName dsAttrTypeStandard:UniqueID dsAttrTypeStandard:PrimaryGroupID dsAttrTypeStandard:GeneratedUID externalbinary:dsAttrTypeStandard:JPEGPhoto" > /usr/local/share/import.txt
echo $USER:$UID:$(id -g):$(dscl . -read /Users/$USER GeneratedUID | cut -d' ' -f2):/path/to/picture/picture.jpg >> /usr/local/share/import.txt
dscl . -delete /Users/$USER JPEGPhoto
dsimport /usr/local/share/import.txt /Local/Default M -u user_you_want_to_update
rm /usr/local/share/import.txt

exit 0

Have tested executing the script with sudo privs and it worked as designed. Will test executing it with a policy, but anticipate the same outcome since JSS acts with root privs. To use this script, update the variables USER and UID at the beginning of the script, update the path to the picture in line 11 (I placed mine in /Library/User Pictures/Custom/logo.jpg). As it happens, the user I'm updating the profile picture for is my hidden admin that support staff use, so on line 13, I wrote out that username explicitly even though it's the same user I defined in the variable in line 7. If you are using this script to update a user picture for a different user or a non-admin user, you may need to do some more testing.

Thanks for the script!

zanb
New Contributor III
Do I need to define $USER and $UID?

Yes. Generally, in scripting communities, people will often declare variables with generic terms. In Bash communities, it is often connoted in uppercase (e.g. $USER_NAME or $GROUPID).

Also, I would advise against using subshell commands $() inline an entire command, as it makes scripts hard to read or diagnose, and if your subshell returns a newline, it can sometimes cause unwanted results. If you want to insert a programmatic string, I'd suggest capturing it in a variable using double quotes:

ugroupID="$(id -g)"
ugenID="$(dscl . -read /Users/$USER GeneratedUID | cut -d' ' -f2)"

Personally I like to put other variables, such as paths, into variables at the top of my scripts so they can be easily changed, should the need come up.

picPath="/path/to/picture/picture.jpg"
outFile="/path/to/import.txt"

Then use the variables in the long string:

echo ${USER}:${UID}:${ugroupID}:${ugenID}:"${picPath}" >> "${outFile}"

Also, encapsulating your variables and double-quoting paths will help ensure your script won't break in case there are spaces in your path, etc.

IT-Chris
New Contributor III

Update on this.
This does work as a script and a policy on 10.14.x

dscl . delete /Users/admin jpegphoto
dscl . delete /Users/admin Picture
dscl . create /Users/admin Picture "/Library/User Pictures/wunderman.tif"

but since its a poilcy script make sure you use
sudo and use the correct path to /library/User Pictures/Sports/Hockey.tiff
you can not use the " " for full path name

KMak84
Contributor

Hi @pranzinic do you mind sharing the exact script that worked for you?
I have an admin account that needs the same profile pic to 400+ macs, with my own pic
Thanks

landon_Starr
Contributor

@k84 This is what I'm using:

#!/bin/sh

# Get Logged in User
loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");'`

# Delete any Photo currently used.
dscl . delete /Users/$loggedInUser jpegphoto
sleep 1
# Delete File path
dscl . delete /Users/$loggedInUser Picture
sleep 1
# Set New Icon
dscl . create /Users/$loggedInUser Picture "/Library/User Pictures/yourpicturehere.tif"

casafrancisco
New Contributor III

@landon_Starr does this work for you on Mojave? It seems to work for us, but after a restart all icons that I used to adjust with this script are now plain grey silhouette of a person. Our computers run FileVault, not sure if that is part of it as well as we enable FileVault via policy and it activates after the restart.