0 Votes

Wallpaper Archive

Last modified by Sirius Rayner-Karlsson on 2025/02/21 12:02

After obtaining a bunch of wallpaper images in different resolutions, I started pondering how to structure them, and then also how to automatically update each of the two screens with new wallpapers every so often. And I quite like neat little Bash solutions, so here is what I came up with.

First, create "Wallpapers" folder in ~/Pictures/.

Then create folders named for resolutions inside ~/Pictures/Wallpapers/

I ended up with the following:

Pictures/
└── Wallpapers
    ├── 1280x800
    ├── 1680x1050
    ├── 1920x1080
    ├── 1920x1200
    ├── 2560x1080
    ├── 2560x1440
    ├── 2560x1600
    ├── 3840x2160
    ├── 3840x2400
    ├── 5120x1440
    ├── 5120x2880
    ├── 7680x4320
    └── OddResolution

 

Next, it was how to scan a bunch of images and copying them into the correct folders. The bash function in my .bashrc looks like this.

function CopyWallPapers () {
  WPDIRS=(~/Pictures/Wallpapers/*)
  chmod 750 .
  for i in $( seq 0 $(( ${#WPDIRS[@]} - 1 )) )
  do
    echo ${WPDIRS[$i]##*/}
    for file in *.{jpg,png,jpeg,JPEG,JPG,PNG,Jpg}
    do
      chmod 644 "$file"
      if [[ "${WPDIRS[$i]##*/}" != "OddResolution" ]]
      then
        file "$file" | grep ${WPDIRS[$i]##*/} > /dev/null
        if [[ $? -eq 0 ]]
        then
          mv -n -- "$file" ${WPDIRS[$i]}/"$(echo $file | tr '[A-Z]' '[a-z]')"
        fi
      fi
      if [[ "${WPDIRS[$i]##*/}" == "OddResolution" ]]
      then
        mv -n -- "$file" ${WPDIRS[$i]}/"$(echo $file | tr '[A-Z]' '[a-z]')"
      fi
    done
  (
    cd ${WPDIRS[$i]}
    let n=$(ls -1 [JP][0-9][0-9]*.{jpg,png}|wc -l)
    let n=$n+1
    for file in *
    do
      case "$file" in
        [JP][0-9]*)
          :
          ;;
        *.jpg|*.jpeg|*.JPG|*.JPEG)
          mv "$file" $(printf J%07d.jpg $n)
          ;;
        *.png|*.PNG)
          mv "$file" $(printf P%07d.png $n)
          ;;
      esac
      let n=$n+1
    done
  )
  done

}

This function is in two parts. I initialise WPDIRS as an array of the directories in ~/Pictures/Wallpapers/ and as those directories are named for resolutions, I can loop over how many (${#WPDIRS[@]}) such directories there are. The array is 0-indexed, hence the minus one in there. I get the name of the directory with a neat little bashism - ${WPDIRS[$i]##*/}. What this does, is the for loop iterates over the sequence 0 through to the number of elements in the array minus one, then I expand what the array element actually is (which is '/home/sirius/Pictures/Wallpapers/1280x800' etc) and then use the neat little bash thing '##*/' which will strip from the left everything before the last '/' which will give me just '1280x800'. 

I can then loop over all the files I want to copy and use "file" command which will tell me what it is, and in the case of images, what their resolution is. If I then grep for that resolution, I can work on the returncode ($?) from grep and move the file into the directory. It is not optimised, because that would take much more thinking and probably using an array to avoid querying the files more than once.

Second half of the function deals with the resolution target directory after the files have been copied. In a sub-shell, jump into the resolution directory and then rename files that does not match the pattern J or P followed by digits, ending in .jpg or .png. The move command also will avoid over-writing existing files.

This allowed me to process about ten thousand images into a dozen specific directories based on resolution in about 30 minutes.

The second function is this:

function wallpaperz () {
  (
    FILES2560x1600=(Pictures/Wallpapers/2560x1600/*)
    FILES3840x2160=(Pictures/Wallpapers/3840x2160/*)
    while true
    do
      RND=$(( $RANDOM % ${#FILES3840x2160[@]} ))
      xwallpaper --output DP-0.8 --zoom ${FILES3840x2160[$RND]};
      RND=$(( $RANDOM % ${#FILES2560x1600[@]} ))
      xwallpaper --output DP-2 --zoom ${FILES2560x1600[$RND]}
      sleep 300
    done
  ) & disown
}

I make two arrays based on two distinct resolutions (it is possible to combine them). Then loop and take the remainder of the division of $RANDOM (random number up to 32768) with how many images in the array and then set the distinct display output with this image. Rinse and repeat for the other screen / output. Sleep for five minutes, then do it again. Enclosing it within parenthesis runs this in a subshell - and the ampersand will background the task. 'disown' will detach it from your shell and terminal, meaning you can close the window and shell and it is still running.

I am fairly happy with this as a solution. 😀