I am very new to Perl and this is the first program I've written that I consider to be useful.

The program selects a random image to be used as a background for IceWM by editing the relevant line in ~/.icewm/preferences. It then checks to see if IceWM is running. If it is, it restarts icewmbg. If it is not, it starts icewm-session.

I've edited my .xinitrc file to call this program on startx and I have also added "F2 = icewmRandombg" to my ~/.icewm/keys file so pressing F2 gives me a new background.

I'm fairly certain the second chdir command isn't necessary, but I'm not absolutely certain, and it's not hurting anything, so I left it. I put it there so icewm-session would be called from my home directory.

#!/usr/bin/perl -w # This program edits ~/.icewm/preferences to set a random wallpaper. # It then checks to see if IceWM is running. If it is, it restarts # icewmbg. If it isn't it starts icewm-session. use strict; my $image_directory = "/home/jivy/media/images/wallpaper"; my @image_files = glob "$image_directory/*"; my $wallpaper = $image_files[rand @image_files]; chdir "/home/jivy/.icewm" or die "Cannot change to .icewm: ($!)"; my $pref = "preferences"; my $new_pref = "preferences.tmp"; my $bak = "preferences.bak"; open PREF, "< $pref"; open NEW_PREF, ">> $new_pref"; while (<PREF>) { s#$image_directory/.*#$wallpaper"#; print NEW_PREF $_; } close PREF; close NEW_PREF; rename ($pref,$bak); rename($new_pref,$pref); chdir "/home/jivy" or die "Cannot change to jivy: ($!)"; if (`ps -e | grep icewm-session`) { exec "icewmbg -r"; } else { exec "icewm-session"; }

Replies are listed 'Best First'.
Re: Random Desktop Background for IceWM
by CountZero (Bishop) on Apr 06, 2009 at 05:59 UTC
    A few (nit-picking) comments about general coding style (your program wil work OK without applying them, but in larger and more complicated programs, it can make a difference):
    • Use single quotes whereever possible rather than double quotes. This will save you from the effects of unwanted interpolation.
    • Use lexical file-handles and surround your file operations with the smalles scope possible (a loop, a block, ...). The handles will close automatically when you leave the scope.
    • Use the three argument form of open, it is safer than the two argument form.
    One final comment: after running your program, you now have an unneccessary "temporary" preferences.tmp file in your system. Perhaps you can have a look at File::Temp that can be used to create and open temporary files in a safe way and these temporary files can be made to disappear automatically once your program finishes.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Thank you for taking the time to reply and suggest improvements. Taking them in order:

      I have been trying to remember to use single quotes but I keep forgetting. I will keep working on that.

      If I understand you right, I should do something like this:

      my $pref = "preferences"; my $new_pref = "preferences.tmp"; my $bak = "preferences.bak"; { my $pref = "preferences"; my $new_pref = "preferences.tmp"; my $bak = "preferences.bak"; open PREF, "< $pref"; open NEW_PREF, ">> $new_pref"; while (<PREF>) { s#$image_directory/.*#$wallpaper"#; print NEW_PREF $_; } rename ($pref,$bak); rename($new_pref,$pref); } chdir "/home/jivy" or die "Cannot change to jivy: ($!)"; if (`ps -e | grep icewm-session`) { exec "icewmbg -r"; } else { exec "icewm-session"; }
      Meaning that I don't use specific close PREF and close NEW_PREF commands.

      I had not seen the three-argument form of open but I looked it up after reading your post. That makes sense.

      There is no extra tmp file hanging around. It is renamed to preferences in line 35. But I will do the suggested research for future use.

        What I meant was to use lexical filehandles:
        { open my $PREF, '<', $pref; open my $NEW_PREF, '>>', $new_pref; while (<$PREF>) { s#$image_directory/.*#$wallpaper"#; print $NEW_PREF $_; }
        Once you leave this block, the filehandles go away and the connections to your files are closed.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Random Desktop Background for IceWM
by ambrus (Abbot) on Apr 07, 2009 at 14:44 UTC

    Nice. I once wrote a script to launch xterms with random background color. I'm not using that anymore because now I'm committed to light grey text over black background.

    Update: by the way, my current xinitrc script starts just icewm instead of icewm-session, and sets the background with Imagemagick's display program like display -window root ~/.xbg.

    Update 2010-07-04: see also GNOME Random Wallpaper Picker.

      Thank you

      I hadn't even thought about using display to set backgrounds.