How can I programmatically change the background in Mac OS X?

Question:

How would I go about programmatically changing the desktop background in Mac OS X? I’d like to use python, but I’m interested in any way possible. Could I hook up to Terminal and call a certain command?

Asked By: stalepretzel

||

Answers:

You can call “defaults write com.apple.Desktop Background …” as described in this article: http://thingsthatwork.net/index.php/2008/02/07/fun-with-os-x-defaults-and-launchd/

The article also goes into scripting this to run automatically, but the first little bit should get you started.

You might also be interested in the defaults man pages: http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/defaults.1.html

Answered By: Matt Miller

From python, if you have appscript installed (sudo easy_install appscript), you can simply do

from appscript import app, mactypes
app('Finder').desktop_picture.set(mactypes.File('/your/filename.jpg'))

Otherwise, this applescript will change the desktop background

tell application "Finder"
    set desktop picture to POSIX file "/your/filename.jpg"
end tell

You can run it from the command line using osascript, or from Python using something like

import subprocess

SCRIPT = """/usr/bin/osascript<<END
tell application "Finder"
set desktop picture to POSIX file "%s"
end tell
END"""

def set_desktop_background(filename):
    subprocess.Popen(SCRIPT%filename, shell=True)
Answered By: dF.

To add to Matt Miller’s response: you can use subprocess.call() to execute a shell command as so:

import subprocess
subprocess.call(["defaults", "write", "com.apple.Desktop", "background", ...])
Answered By: Adam Rosenfield

You could also use py-appscript instead of Popening osascript or use ScriptingBridge with pyobjc which is included in 10.5 but a bit more cumbersome to use.

Answered By: d0k

If you are doing this for the current user, you can run, from a shell:

defaults write com.apple.desktop Background '{default = {ImageFilePath = "/Library/Desktop Pictures/Black & White/Lightning.jpg"; };}'

Or, as root, for another user:

/usr/bin/defaults write /Users/joeuser/Library/Preferences/com.apple.desktop Background '{default = {ImageFilePath = "/Library/Desktop Pictures/Black & White/Lightning.jpg"; };}'
chown joeuser /Users/joeuser/Library/Preferences/com.apple.desktop.plist

You will of course want to replace the image filename and user name.

The new setting will take effect when the Dock starts up — either at login, or, when you

killall Dock

[Based on a posting elsewhere, and based on information from Matt Miller’s answer.]

Answered By: Clinton Blackmore

I had this same question, except that I wanted to change the wallpaper on all attached monitors. Here’s a Python script using appscript (mentioned above; sudo easy_install appscript) which does just that.

#!/usr/bin/python

from appscript import *
import argparse

def __main__():
  parser = argparse.ArgumentParser(description='Set desktop wallpaper.')
  parser.add_argument('file', type=file, help='File to use as wallpaper.')
  args = parser.parse_args()
  f = args.file
  se = app('System Events')
  desktops = se.desktops.display_name.get()
  for d in desktops:
    desk = se.desktops[its.display_name == d]
    desk.picture.set(mactypes.File(f.name))


__main__()
Answered By: Glen Balliet

Another way to programmatically change the desktop wallpaper is to simply point the wallpaper setting at a file. Use your program to overwrite the file with the new design, then restart the dock: killall Dock.

The following depends on Xcode, lynx and wget, but here’s how I automatically download and install a monthly wallpaper on Mountain Lion (shamelessly stolen and adapted from http://ubuntuforums.org/showthread.php?t=1409827) :

#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/local/bin
size=1440
dest="/usr/local/share/backgrounds/wallpaperEAA.jpg"
read -r baseurl < <(lynx -nonumbers -listonly -dump 'http://www.eaa.org/en/eaa/aviation-education-and-resources/airplane-desktop-wallpaper' | grep $size) &&
wget -q "$baseurl" -O "$dest"
killall Dock

Dump it into /etc/periodic/monthly/ and baby, you got a stew goin!

Answered By: DrumEater

The one-line solution for Mavericks is:

osascript -e 'tell application "Finder" to set desktop picture to POSIX file "/Library/Desktop Pictures/Earth Horizon.jpg"'
Answered By: aculich

Building on dF.’s answer, you could do it with Apple Script without Finder and you can do it for multiple desktops.

To set the wallpaper for desktop i (desktop numbers start at 1):

tell application "System Events"
    set currDesktop to item i of desktop
    set currDesktop's picture to "image_path"
end tell

This is what I ended up doing (in Python):

SET_DESKTOP_IMAGE_WRAPPER = """/usr/bin/osascript<<END
tell application "System Events"
{}
end tell
END"""

SET_DESKTOP_IMAGE = """
set currDesktop to item {idx} of desktops
set currDesktop's picture to "{image_path}"
"""

def set_wallpapers(images):
    """ images is an array of file paths of desktops """

    script_contents = ""
    for i, img in enumerate(images):
        idx = i+1
        script_contents += SET_DESKTOP_IMAGE.format(idx=idx, image_path=img)

    script = SET_DESKTOP_IMAGE_WRAPPER.format(script_contents)
    subprocess.check_call(script, shell=True)

Sometimes, the desktop images don’t appear immediately. I don’t know why this happens, but restarting the dock fixes it.
To do that from python:

subprocess.check_call("killall Dock", shell=True)

By the way, you can get the number of desktops on the system using this AppleScript code:

tell application "System Events"
    get the number of desktops
end tell

you can use that with subprocess.check_output to get the output

Answered By: jrizkalla

There are a default collection of quality images in:

/Library/Desktop Pictures/

To automate the selection of one of these across all desktops, without a 3rd party dependency:

osascript -e 'tell application "System Events" to set picture of every desktop to "/Library/Desktop Pictures/Solid Colors/Stone.png"'
Answered By: 0xADADA

Put the following in your ~/.bashrc

function wallpaper() {
    wallpaper_script="tell application "Finder" to set desktop picture to POSIX file "$HOME/$1""
    osascript -e $wallpaper_script 
}

Use like so:

wallpaper /path/to/image.png
Answered By: James Raubenheimer

You can do this without killall Dock by running a Swift script from your Python script.

Create a chwall.swift file with the following code:

#!/usr/bin/env swift

import Cocoa

do {
    // get the main (currently active) screen
    if let screen = NSScreen.main {
        // get path to wallpaper file from first command line argument
        let url = URL(fileURLWithPath: CommandLine.arguments[1])
        // set the desktop wallpaper
        try NSWorkspace.shared.setDesktopImageURL(url, for: screen, options: [:])
    }
} catch {
    print(error)
}

Now run the above chwall.swift file with subprocess in Python.

import subprocess

subprocess.run(["./chwall.swift", "/path/to/your/wallpaper/file.png"])
Answered By: tnychn
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.