Hi
I have 2 directories t1 and t2 with some files in it. I have to see whether the files present in t1 is also there in t2 or not. Currently, both the directories contain the same files as shown below:
$ABC.TXT
def.txt
Now, when I run the below script, it tells def.txt is found, $ABC.TXT not found. Since the filename itself contains wildcard, grep seems to be having some issue:
#!/usr/bin/perl
my @src=`ls /home/t1/`;
my @dest=`ls /home/t2/`;
foreach my $file (@src){
@match=grep(/$file/, @dest);
if (@match==0){
print "Found $file";
}else{
print "Not found $file";
}
}
Output:
Found def.txt
Not found $ABC.TXT
Please advice. I have put 2 files for samples. I also have some files like $$ABC.TXT, $$$ABC.TXT.
Hi Jerry
Thanks for your reply. The number of files I have in the source and destination directories are around 50k, and hence using a nested for will cause some performance issue.
Have you tested or benchmarked this claim?
The "grep" method essentially does a nested loop as well. It's just more concise and a more "Perlish" way of doing things.
With a setup consisting of two directories "t1" and "t2" having 10,005 identical files, my benchmark shows this -
(A) Perl's "grep" operator takes 148 seconds on an average to compare 10,005 files in directories "t1" and "t2".
(B) Perl's nested loop method takes 7.27 seconds on an average to compare 10,005 files in directories "t1" and "t2".
tyler_durden
---------- Post updated 02-10-11 at 01:44 PM ---------- Previous update was 02-09-11 at 02:15 PM ----------
For academic interest, if you were looking for a solution for the problem mentioned in your original post, you will have to quote the string you are searching for, so that it isn't interpolated -
$
$ # Elements $C, $$D, $$$E of array @x exist in array @y, but
$ # that is not reported because Perl tries to interpolate
$ # the "$" regex metacharacter.
$
$ perl -le '@x = qw( B $C $$D $$$E F );
@y = qw( A B $C $$D $$$E );
foreach $i (@x) {
$exists = grep {/$i/} @y;
printf("%-10s %-20s in \@y\n", $i, $exists==1 ? "exists" : "does not exist");
}'
B exists in @y
$C does not exist in @y
$$D does not exist in @y
$$$E does not exist in @y
F does not exist in @y
$
$
$ # Works fine with quotemeta function
$
$ perl -le '@x = qw( B $C $$D $$$E F );
@y = qw( A B $C $$D $$$E );
foreach $i (@x) {
$exists = grep {/\Q$i\E/} @y;
printf("%-10s %-20s in \@y\n", $i, $exists==1 ? "exists" : "does not exist");
}'
B exists in @y
$C exists in @y
$$D exists in @y
$$$E exists in @y
F does not exist in @y
$
$