lisaw has asked for the wisdom of the Perl Monks concerning the following question:

Hello Perl-Monks and Happy New Year!

Here's what I have going on...An administrator can add/upload any number of product images to a particular product category directory but can only utilize 10 of those images for display with the product. There aren't many products so I'm using a flat-file db. When the product images are uploaded they are renamed to contain the product id number. This all works great except when the product is removed from the database...the only product images removed are the ones actually being utilized for display. Here's a quick snip of the code that shows the removal of the photo-1/thumb-1 (this is the same for display images 2-10):
if ($photo1 ne "") { {system("rm $photodir/$category_id_number/$photo1");} my @resize1 = split(/\./, $photo1); my $photo1t = $resize1[0] . "-T." . $resize1[1]; {system("rm $photodir/$category_id_number/$photo1t");} }
Is there a way to look through a directory to see if any image files contain the id number and simply remove all images that contain the id number?

Thank you!

Replies are listed 'Best First'.
Re: Removing Multiple Image Files
by jettero (Monsignor) on Jan 05, 2007 at 02:51 UTC

    I have a handfull of comments to make. I hope they are helpful.

    First, if($photo1 ne "") isn't very perl-y ... Try if($photo1). There's a lot of differnt kinds of false in perl, undef, and "" are among them.

    Second, you should be really careful about embedding filenames in system() calls when they might have been written by some nefarious "customer." If you choose system("rm", "$photo/$cat$id/$thing") (i.e. multi arg call), then you don't have to worry about evil shell escapes. That could save you a lot of trouble one day.

    Lastly, your actual question, I think can be solved with opendir:

    opendir my $dir, "$photodir/$category" or die "didn't work: $!"; while( my $ent = readdir $dir ) { next unless $ent =~ m/something/; # unlink("$p/$c/$ent") or die "didn't work: $!"; } closedir $dir; }

    Probably some people would also recommend File::Find (or a simple glob like the above) — and those solutions may be easier for you, but I like the old fasioned stuff. Actually, having re-read that it's 10 or so images I'd say the glob is probably best.

    Update 2 ikegami: In point of fact, I usually use a variant of if(defined $something) myself. I objected to ne "" without thinking it through clearly.

    -Paul

      First, if($photo1 ne "") isn't very perl-y ... Try if($photo1).

      Let's hope there's no photos named 0. An odd name, I'll grant you, but your suggestion weakens the code.

      ( By the way, it probably be best if $photo1 was undefined and the if was if (defined $photo1). It's easier to catch errors when using undef over the empty string to mark the absense of something, since using undef as a string leads to a warning. )

Re: Removing Multiple Image Files
by almut (Canon) on Jan 05, 2007 at 02:48 UTC

    Maybe something like this?

    unlink glob "$photodir/$category_id_number/*$id*";

    (adjust the glob pattern as needed)

Re: Removing Multiple Image Files
by sgifford (Prior) on Jan 05, 2007 at 05:04 UTC
    To expand a little on something jettero mentioned, make sure you think about the security issues involved. Make sure to run Perl in taint mode, and make sure all of the variables are either completely under your control (i.e. hardcoded into the program or a configuration file) or else fully sanitized. Otherwise, think about what could happen if $category_id_number contained a path with .. elements; a path could be constructed to any file on your filesystem, and if the Web server user had permission to unlink it, that would be that. Also think about using Perl functions when possible, such as unlink instead of rm. They're safer, and will give you better performance, too.