Changing wallpapers using a shell script

When we consider shell scripts, it is usually for some repetitive tasks. It is usually combined with cron to automate the tasks.

I guess what works for system productivity might as well work for the fun activity of changing the desktop wallpaper. Every hour.

First off, I am using Openbox for my desktop session. For setting the wallpaper, I am using feh to set the wallpaper.

# script to set the wallpaper
# by Nandan Bhat at Linux Training & Certification
# on September 25, 2012
# Available under Creative Commons Attribution-ShareAlike 2.5 India ( License
# random selection of jpeg file from a given folder 
# or the file (single) given
# or from a random jpeg from a  default folder

# do we have feh? we require it for setting the wallpaper
# also note /usr/bin/which is the path in my currently used Linux distribution - Fedora. 
# change as per your used Linux distribution
FEH=$(/usr/bin/which feh 2>/dev/null)
FEH_OPTS=" --bg-scale "

# no feh? cannot continue, so exit with an error
if [ -z "$FEH" ]
   echo "[Error] feh is not available. cannot continue. exiting ..." 1>&2
   exit 1

# echo "[DEBUG] $FEH = $FEH" 1>&2

# do we have a directory supplied from positional parameter 1 ?
if [ -n "$1" ]
   # echo "[DEBUG] Got $1 = $1" 1>&2
   # is it a directory ?
   if [ -d "$1" ]
      # echo "[DEBUG] positional parameter $1 set as $BASEDIR" 1>&2
   # if not a directory, is it a JPEG file? feh can only manage jpegs
   elif [  $(file "$1" | grep JPEG | wc -l) -eq 1  ]
      # echo "[DEBUG] $1 set as $CHOSENFILE" 1>&2
   # we have not received a directory or a file
   # use default as /data/wallpapers                        ###    USE YOUR FAVOURITE WALLPAPER LOCATION HERE    ###
   # echo "[DEBUG] $BASEDIR = $BASEDIR" 1>&2

# if we don't have a file chosen already,
# we have to choose a random jpeg file

if [ -z "$CHOSENFILE" ]
   # we need a random file; check if there is at least one jpeg
   NUMJPEGS=$(file "${BASEDIR}"/* | grep JPEG | wc -l)

   # echo "[DEBUG] $NUMJPEGS = $NUMJPEGS" 1>&2

   # no jpegs among wallpapers? cannot continue with feh then. exit with error
   if [ $NUMJPEGS -eq 0 ]
      echo "[Error] No JPEG files in ${BASEDIR}. exiting ..." 1>&2
      exit 2

   # populate an array with paths of the image files

   # for every image, if it is a jpeg, add path to array element
   for IMAGEFILE in "${BASEDIR}"/*
      file "$IMAGEFILE" | grep -q JPEG

      if [ $? -eq 0  ]
         # add 1 to COUNTER

         # echo "[DEBUG] $IMAGEFILE added to $IMAGESARRAY" 1>&2

   # choose a number with $RANDOM bash variable
   # limit it in range from 0 to COUNTER
   # this will be the array index position for the image
   # chosen file is the path stored in array index position


# we should have $CHOSENFILE by now.
# nothing left to do but set the wallpaper
# echo [DEBUG] "$FEH" "$FEH_OPTS" "$CHOSENFILE" 1>&2

if [ $? -eq 0 ]
   # exit with success
   exit 0
   echo "[DEBUG] Oops! This script did a boo-boo! Could not set wallpaper with $FEH" 1>&2
   exit 3
# end of script

If you feel this script is too elaborate for the purpose, please feel free to comment on it and give us a better one. If you are wondering about the code appearance, it was done with (what else?) a WordPress plugin – Crayon syntax highlighter.

This code was saved in $HOME/bin/ and was given executable rights, with a crontab configured to run it every hour. Since cron is not running in the user session, it is unable to use the graphics (simplified explanation). The crontab entry must have

DISPLAY=:0.0 $HOME/bin/