in reply to Compare 2 arrays

First off, take a hard look at your nested loop. It may help to rewrite it a little to see what's going on:

foreach $name (@name) { last if ($name =~ $filename); unlink($files . "\\" . $filename) or warn qq{cannot delete $filename: $!+}; last; }

which is the same as:

if ($name[0] !~ $filename) { unlink($files . "\\" . $filename) or warn qq{cannot delete $filename: $!+}; }

because the two uses of last mean that you only ever get 1 iteration of the nested loop. That code ensures you delete the current file unless the first name happens to match the current file name.

However when you want to answer a "is it in the set" question use a hash. Consider:

#!\perl\bin\perl use strict; use warnings; my $files = "C:\\Directory"; my $list = "C:\\Test.sdf"; my %keepList; open my $namesIn, '<', $list or die "Failed to open file: $!\n"; while (<$namesIn>) { chomp; $keepList{$_} = 1; } close $namesIn; opendir my ($filesScan), $files; while (my $filename = readdir $filesScan) { next if exists $keepList{$filename}; unlink "$files\\$filename" or warn qq{cannot delete $filename: $!+ +}; } closedir $filesScan;

Note that I haven't tested the code!

Premature optimization is the root of all job security

Replies are listed 'Best First'.
Re^2: Compare 2 arrays
by Marshall (Canon) on Jun 28, 2016 at 00:59 UTC
    I liked your code. A few suggestions, but also not tested!

    • Use "/" instead of "\\" for windows file paths
    • I think some extra filtering is necessary on the $namesIn file?
    • for opendir, add a die message if fails
    • for readdir, skip all but simple files - maybe here makes no difference, but I would do it.
    Perhaps something like this???
    #!usr/bin/perl use strict; use warnings; my $files = "C:/Directory"; my $list = "C:/Test.sdf"; my %keepList; open my $namesIn, '<', $list or die "Failed to open file: $!\n"; # minor updates to this loop ##################### while (my $line = <$namesIn>) #updated ####### { my $sdf_file; #next unless ($sdf_file) = $line =~ /(\w+\.nfo)"$/; #this regex should work equally well next unless ($sdf_file) = $line =~ /(\w+\.nfo)/; $keepList{$sdf_file} = 1; print "keeping $sdf_file\n"; #update for debugging ####### } close $namesIn; opendir my ($filesScan), $files or die "unable to open dir $!"; while (my $filename = readdir $filesScan) { next unless -f "$files/$filename"; #only simple files allowed #skip . and .. or other dirs next if exists $keepList{$filename}; unlink "$files/$filename" or warn qq{cannot delete $filename: $!+} +; } closedir $filesScan;

      Hi Marshall,

      Thank you for your responds and your suggestions. Unfortunately your codes also delete all the files in the directory.

      Please let me know if you have other ideas.

        Looks like the keepList hash is not being populated correctly. I tweaked the code a bit in my post. See how you do with the modifications. I added a print statement. Make sure that it is printing correctly the files that should be kept!

        Update: Another point, when you run the code warnings matter! My previous code with while (<$namesIn>) would have produced a warning if not an outright failure because $line was not declared! The new code, while (my $line = <$namesIn>) "should work". This kind of error is common in untested code. I would have expected that you find that and fix it on your own.

        When debugging code, "print" is your best friend. Add more print statements to see what the code is actually doing. I put in one for the keepList hash because I suspect that is where the problem lies. Add another one before the unlink to see what is going on there. The Perl debugger is also helpful, but print works so well that I seldom need to resort to that even when I am writing C code.

        First, debug the code that reads the SDF file and gets the .nfo file names. Then debug the code that does the unlink (i.e. delete in Windows lingo).

Re^2: Compare 2 arrays
by niceguy (Initiate) on Jun 28, 2016 at 15:49 UTC

    Hi GrandFather,

    Thank you for your responds and your suggested codes but your codes also deletes all the files in the directory.

    Do you have any other ideas?

      It may be that your file lists files to be removed where I assumed it listed files to be kept. You can tell that from the name of the keepList variable. You simply need to change keepList to removeList and change the sense of the exists test.

      Look at the code. Think about the code. Read the documentation for anything you don't understand. If you still can't figure it out, come back and ask about the elements of the code you don't understand.

      Premature optimization is the root of all job security