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

Hi Monks!
I am trying to figure it out what would be the best way to delete some image files from a directory if they match the names found prior in a database, here is what I have so far:
... while (my $row = $sth->fetchrow_hashref()) { my $del_1 = $row->{image_1} || ''; my $del_2 = $row->{image_2} || ''; my $del_3 = $row->{image_3} || ''; my $del_4 = $row->{image_4} || ''; } my $dir_to_open = "../../pics"; opendir(DIR,$dir_to_open) || die("Cannot open directory !\n"); @dir_contents= readdir(DIR); closedir(DIR); foreach $file (@dir_contents){ if(!(($file eq ".") || ($file eq ".."))){ # I want to delete the files found in here if they match what was fou +nd above in the database call } }
I would like to delete the files found if they match what was found above in the database call. Can anybody tell how I could do that? Thanks for the help!

Replies are listed 'Best First'.
Re: Delete files if they match help!
by roboticus (Chancellor) on Jan 07, 2011 at 03:48 UTC

    The function you're looking for is unlink. That should do the trick for you.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: Delete files if they match help!
by Anonyrnous Monk (Hermit) on Jan 07, 2011 at 03:50 UTC

    Maybe I'm misunderstanding... but can't you just try to delete the files returned from the db query — rather than search through and compare with the entire directory listing every time?  If the file doesn't exist in the directory, the unlink call will fail, but so what? it isn't going to hurt the computer.  Something like this:

    while (my $row = $sth->fetchrow_hashref()) { for my $imgfile (map $row->{"image_$_"}, 1..4) { unlink "../../pics/$imgfile"; } }

    And if you don't really care which individual files couldn't be unlinked (by checking the function's return value), you could also pass the entire file list directly to a single unlink call...

    unlink map "../../pics/".$row->{"image_$_"}, 1..4;
      I like this:
      while (my $row = $sth->fetchrow_hashref()) { for my $imgfile (map $row->{"image_$_"}, 1..4) { unlink "../../pics/$imgfile"; } }
      But I will move the files somewhere else instead of deleting it.
      Well, in the database only the name of these files exist, in the directory in spec is where the physical files are, that’s why I need to check if they match first before deleting them, any more feedback? Thanks!

        I'm afraid I still don't understand the need for the extra checking.  If you have a name, say "img_2678.jpg", in the DB that you want to delete from the directory ../../pics, you'd just create the proper path and do

        unlink "../../pics/img_2678.jpg";

        The OS will then try to locate the physical file and, if it's there, delete it.  If it's not there, the unlink call will fail. That's it. No need to first figure out if the directory holds a file img_2678.jpg.

        Or is it that you don't know which directory holds the files? In this case, just check the return value of the unlink call. If it succeeded, you likely picked the right one, otherwise try the next directory candidate.

        (The same general considerations would apply if you're actually going to move the files, instead of deleting them.)

Re: Delete files if they match help!
by k_manimuthu (Monk) on Jan 07, 2011 at 03:51 UTC

    Check the file is exist. if the file exists then process the unlink process

    unlink $file_name if (-e $file_name && -f $file_name)

      TOCTOU, but why? unlink() won't kill your grandma if the file to be deleted does not exist (any more). It will just generate an error ("No such file or directory"). It also generates an error ("Is a directory") when you attempt to delete a directory instead of a plain file (unless you are root, have started perl with the -U flag, and your OS supports unlinking a directory). So, unlink(), check $!, TOCTOU problem gone.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Delete files if they match help!
by toolic (Bishop) on Jan 07, 2011 at 13:41 UTC
    Unrelated to your problem...

    Consider replacing

    opendir(DIR,$dir_to_open) || die("Cannot open directory !\n"); @dir_contents= readdir(DIR); closedir(DIR); foreach $file (@dir_contents){ if(!(($file eq ".") || ($file eq ".."))){ # I want to delete the files }

    with:

    use File::Slurp; for my $file (grep { -f } read_dir($dir_to_open)) { # I want to delete the files }

    File::Slurp is a CPAN module which abstracts away all the open/close/checking details and automatically filters out the special 'dot' directories. The grep -f selects only files.

    You do use strict and warnings, don't you?

      Hi, I am trying to do this like that, but I am missing something:
      use strict; use File::Slurp; ... my $dir_to_open = "../../pics"; my $arch = "../../arch"; while (my $row = $sth->fetchrow_hashref()) { for my $imgfile (map $row->{"image_$_"}, 1..4) { for my $file_to_mv (grep { -f } read_dir($dir_to_open)) { if($file_to_mv=~/$imgfile/) { #move("$dir_to_open/$file_to_mv", $arch); print "Test before move: $dir_to_open/$file_to_mv +<br>"; } } }
      Any help on this one?
        Without more details of what problem you are having, the best help I can offer is to start using print to see if your variables contain what you expect them to contain (Tip #2 from Basic debugging checklist).
Re: Delete files if they match help!
by locked_user sundialsvc4 (Abbot) on Jan 07, 2011 at 16:26 UTC

    To my way of thinking, the best way to handle this is to simply attempt to delete them all.   It’s wasteful to do one directory-search to see if the file exists, only to turn around and (oblige the target computer to) do another one in order to delete them.

    If you have reason to believe that most of the filenames do not exist, and that the number of files which actually do exist is small enough to warrant a scan, then obviously you could request a list of files and cherry-pick from that.   It really depends on what you consider the realistic probability of “file not found” to be.