LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 12-20-2010, 04:44 PM   #1
Kebman
LQ Newbie
 
Registered: Dec 2010
Distribution: Mac OS X
Posts: 4

Rep: Reputation: 0
Question Perl: Counting Files With File::Find


So this is my code:
Code:
#!/usr/bin/perl
# Count every occurence of a certain type of file (*.old) recursively
use strict;
use File::Find;

my $dir = ".";
my $count;

find( sub {if ("$/"!=(/\.old$/)){$count++}},$dir);

print "$count\n";
Modification of code I found here. It works, but I don't really know why.

Q1: Why is each filter hit counted only when the conditional is not true?

Q2: I've tried taking the file type, (.old), and put it into a variable for better usability, but then the script fails.

Last edited by Kebman; 12-20-2010 at 04:49 PM.
 
Old 12-20-2010, 06:42 PM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by Kebman View Post
So this is my code:
Code:
#!/usr/bin/perl
# Count every occurence of a certain type of file (*.old) recursively
use strict;
use File::Find;

my $dir = ".";
my $count;

find( sub {if ("$/"!=(/\.old$/)){$count++}},$dir);

print "$count\n";
Modification of code I found here. It works, but I don't really know why.

Q1: Why is each filter hit counted only when the conditional is not true?

Q2: I've tried taking the file type, (.old), and put it into a variable for better usability, but then the script fails.
First, add

Code:
use warnings;
just before or after

Code:
use strict;
and fix the warnings if any.

Secondly, publish here full non-working code.
 
Old 12-20-2010, 06:49 PM   #3
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
And looking at code at given by the OP http://forums.devshed.com/showthread...24#post1473024 I do not see usage of $/ Perl built-in variable; I do no understand what it has to do with the task.
 
Old 12-21-2010, 10:11 AM   #4
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 59
Quote:
Originally Posted by Sergei Steshenko View Post
And looking at code at given by the OP http://forums.devshed.com/showthread...24#post1473024 I do not see usage of $/ Perl built-in variable; I do no understand what it has to do with the task.
The code on Devshed uses $/ in place of \n in its call to print:
Code:
print "$File::Find::name$/"
I think the OP has misunderstood the original code, and his use of $/ doesn't make any sense at all.
 
1 members found this post helpful.
Old 12-21-2010, 10:22 AM   #5
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 59
Quote:
Originally Posted by Kebman View Post
So this is my code:
Code:
#!/usr/bin/perl
# Count every occurence of a certain type of file (*.old) recursively
use strict;
use File::Find;

my $dir = ".";
my $count;

find( sub {if ("$/"!=(/\.old$/)){$count++}},$dir);

print "$count\n";
Modification of code I found here. It works, but I don't really know why.

Q1: Why is each filter hit counted only when the conditional is not true?

Q2: I've tried taking the file type, (.old), and put it into a variable for better usability, but then the script fails.
I think you've tried rewriting someone else's Perl code without really knowing Perl. $/ is a builtin Perl variable for the default input record separator (it's a newline \n by default). So it makes no sense to test that against a regular expression looking for '.old' at the end of a filename. (See perldoc perlvar for more information on Perl's many builtin variables.)

If you are familiar with Perl and just don't quite get File::Find - which does have an odd API at first - you might check out this article on it: http://www.stonehenge.com/merlyn/LinuxMag/col45.html
 
1 members found this post helpful.
Old 12-21-2010, 11:10 AM   #6
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by Telemachos View Post
The code on Devshed uses $/ in place of \n in its call to print:
Code:
print "$File::Find::name$/"
I think the OP has misunderstood the original code, and his use of $/ doesn't make any sense at all.
I mean the devshed code does not use $/ in 'if' condition/regular expressions.
...
FWIW, if one needs to count files only, he/she should make sure that directories are not counted.
 
Old 12-23-2010, 09:15 AM   #7
Kebman
LQ Newbie
 
Registered: Dec 2010
Distribution: Mac OS X
Posts: 4

Original Poster
Rep: Reputation: 0
First of all, use warnings does not answer my questions.

Second of all, I'd still love to have the questions answered.

Thirdly, thank you very much Telemachos, for giving me a heads up on the $/. I'm now in the process of reading the article you recommended.

Last edited by Kebman; 12-23-2010 at 09:17 AM.
 
Old 12-23-2010, 11:40 AM   #8
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by Kebman View Post
First of all, use warnings does not answer my questions.

Second of all, I'd still love to have the questions answered.

Thirdly, thank you very much Telemachos, for giving me a heads up on the $/. I'm now in the process of reading the article you recommended.
The official documentation: http://perldoc.perl.org/File/Find.html was good enough for me to make me able to use the function.

If you do not understand the documentation, ask specific questions about the things you do not understand.

"use warnings;" is must - Perl runtime will tell you about things which might be wrong (if any). If you do not use "use warnings;", you assume your code has no runtime problems - which is not a good assumption.

You shouldn't be even asking questions unless you have

Code:
use strict;
use warnings;
in place and everything is clean.
 
Old 12-24-2010, 10:31 PM   #9
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 59
In a nutshell, when you call the find method, you pass it two parameters: first a reference to a subroutine (usually) and second a directory location.

The File::Find module starts from the directory location you specify and travels downward recursively (that is into every sub-dir and sub-dir of that sub-dir etc.). The module then calls the code in the subroutine on every item (file or directory) that is found in that downward spiral.

So here's a case somewhat like yours: let's imagine that I want to find all the files ending in '.rb' in the current directory ('.') or any subdirectory of the current directory. I could do this:

Code:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;

my $dir = '.';
my $count;

find(sub{$count++ if $File::Find::name =~ /\.rb$/}, $dir);

print $count, "\n";
The File::Find module exports $File::Find::name as a special variable: it contains the full name and pathname of each item seen as File::Find works. The subroutine above increases $count (that's the effect of $count++) if the item has '.rb' at the end of its name. (That's the effect of the if and the regular expression.)

If the subroutine is simple like this, you can include it inline in the call to find, but if it's more complicated, you can store it separately and pass a reference to the subroutine. For example:

Code:
find(\&find_rubies, $dir);

sub find_rubies {
    # imagine this were long and complicated
    $count++ if $File::Find::name =~ /\.rb$/
}
or

Code:
my $find_rubies = sub {
    # imagine this were long and complicated
    $count++ if $File::Find::name =~ /\.rb$/
};

find($find_rubies, $dir);
Those two are effectively the same thing in slightly different ways. I prefer the second style (storing an anonymous subroutine as a reference), but tastes vary.

Last edited by Telemachos; 12-24-2010 at 10:35 PM. Reason: Change subroutine name
 
Old 12-24-2010, 11:54 PM   #10
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by Telemachos View Post
In a nutshell, when you call the find method, you pass it two parameters: first a reference to a subroutine (usually) and second a directory location.

The File::Find module starts from the directory location you specify and travels downward recursively (that is into every sub-dir and sub-dir of that sub-dir etc.). The module then calls the code in the subroutine on every item (file or directory) that is found in that downward spiral.

So here's a case somewhat like yours: let's imagine that I want to find all the files ending in '.rb' in the current directory ('.') or any subdirectory of the current directory. I could do this:

Code:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;

my $dir = '.';
my $count;

find(sub{$count++ if $File::Find::name =~ /\.rb$/}, $dir);

print $count, "\n";
The File::Find module exports $File::Find::name as a special variable: it contains the full name and pathname of each item seen as File::Find works. The subroutine above increases $count (that's the effect of $count++) if the item has '.rb' at the end of its name. (That's the effect of the if and the regular expression.)

If the subroutine is simple like this, you can include it inline in the call to find, but if it's more complicated, you can store it separately and pass a reference to the subroutine. For example:

Code:
find(\&find_rubies, $dir);

sub find_rubies {
    # imagine this were long and complicated
    $count++ if $File::Find::name =~ /\.rb$/
}
or

Code:
my $find_rubies = sub {
    # imagine this were long and complicated
    $count++ if $File::Find::name =~ /\.rb$/
};

find($find_rubies, $dir);
Those two are effectively the same thing in slightly different ways. I prefer the second style (storing an anonymous subroutine as a reference), but tastes vary.
All this is written in the official documentation.
 
Old 12-25-2010, 02:49 PM   #11
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 59
Quote:
Originally Posted by Sergei Steshenko View Post
All this is written in the official documentation.
Yes, I'm well aware of that. We've had this conversation before, but the documentation can sometimes be overwhelming for new programmers.

What I wrote is all in the docs, but I didn't include everything in the docs. Sometimes it helps to start with a short, somewhat simplified version.
 
Old 12-25-2010, 09:55 PM   #12
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by Telemachos View Post
... the documentation can sometimes be overwhelming for new programmers. ...
English comprehension skills are taken care of in other than this forum places.

...

It looks to me that the OP's problem is not specifically File::Find module, but much more basic things in Perl. Or even in programming in general - like the issue of types and comparing apples to oranges.

Last edited by Sergei Steshenko; 12-25-2010 at 09:57 PM.
 
Old 01-04-2011, 08:12 PM   #13
Kebman
LQ Newbie
 
Registered: Dec 2010
Distribution: Mac OS X
Posts: 4

Original Poster
Rep: Reputation: 0
Please stop trolling, Sergei. Telemachos is doing a great job explaining. Thanks T!

Here's what use warnings; returns:
Code:
Argument "" isn't numeric in numeric ne (!=) at countfilesoftype.pl line 9.
I don't understand what that means.

Again, the (quite specific) questions are:

Q1: Why is each filter hit counted only when the conditional is not true?

You should think it would work when it was set to true. (I've tested the script, and it always returns the correct number of files.)

Q2: I've tried taking the file type, (.old), and put it into a variable for better usability, but then the script fails.

I gather this is an issue with how Regular Expressions are used, and I have a hunch it may have something to do with line breaks or something in that order, but I just don't know for sure - or how to fix it. I will be very greatful for help with this.

Last edited by Kebman; 01-04-2011 at 08:15 PM. Reason: Because I always edit
 
Old 01-04-2011, 08:40 PM   #14
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by Kebman View Post
Please stop trolling, Sergei. Telemachos is doing a great job explaining. Thanks T!

Here's what use warnings; returns:
Code:
Argument "" isn't numeric in numeric ne (!=) at countfilesoftype.pl line 9.
I don't understand what that means.

Again, the (quite specific) questions are:

Q1: Why is each filter hit counted only when the conditional is not true?

You should think it would work when it was set to true. (I've tested the script, and it always returns the correct number of files.)

Q2: I've tried taking the file type, (.old), and put it into a variable for better usability, but then the script fails.

I gather this is an issue with how Regular Expressions are used, and I have a hunch it may have something to do with line breaks or something in that order, but I just don't know for sure - or how to fix it. I will be very greatful for help with this.

So, what exactly you don't understand in the item in bold ? It's a sentence in English. The warning illustrates your fundamental problem WRT types, i.e. what types (in programming) are for, which types are compatible and which are not, etc. Or apples vs oranges.

All the rest of your questions are secondary - because the warning tells you that a particular line of your code is senseless, and the senseless line is the main one in a sense it is supposed to produce the correct hit.

And, by the way, are familiar with the concept of WEB search ? I.e. have you tried to enter

Argument "" isn't numeric in numeric ne (!=)

into a WEB search engine ? Third match from Yahoo appears to be relevant.
...
Are you familiar with the RTFM concept ? How about 'man perl' for starters ? In my case it produces among other things:

Code:
     67            perldiag            Perl diagnostic messages
     68            perllexwarn         Perl warnings and their control
and 'perldoc perldiag' does have an explanation of the warning.

Last edited by Sergei Steshenko; 01-04-2011 at 08:45 PM.
 
Old 02-03-2011, 08:30 PM   #15
Kebman
LQ Newbie
 
Registered: Dec 2010
Distribution: Mac OS X
Posts: 4

Original Poster
Rep: Reputation: 0
Sergei, When people get pissed off by your posts or the way you act, do you really think your advice is wanted? If you stopped being so rude and condescending, I might choose to listen to you. Heck, if you just bothered to answer the questions plain and simple, instead of complaining about my mental abilities, when it's obviously you who's lacking in mental abilities for explaining things in an understandable and polite fashion, then I might listen to you. However as it is, I choose to ignore you.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Perl File::Find work on remote systems ? hattori.hanzo Programming 0 11-19-2010 05:08 PM
How do I Find and Replace text within files using Perl (no one-liners please) GuerillaSquad Programming 3 12-31-2009 09:01 AM
Perl find file and then replace string in file moos3 Programming 5 07-29-2009 07:10 AM
How can I find a window of text in a file using Perl? hgate73 Programming 10 04-30-2009 02:13 PM
perl(Cwd) perl(File::Basename) perl(File::Copy) perl(strict)....What are those? Baldorg Linux - Software 1 11-09-2003 08:09 PM


All times are GMT -5. The time now is 09:03 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration