Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Hi Monks could you pls help Perl dummy user

by sibyurik (Novice)
on Dec 17, 2014 at 00:54 UTC ( [id://1110583]=perlquestion: print w/replies, xml ) Need Help??

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

I need analyze dir structure and find all files that larger than 515 kbytes and recursion doesn't work i have no clue why? Please help me without fancy module and package style. Thx a lot

#!/usr/bin/perl # #Author: Yury Sibirski #Name: users_home_dir #Date: 16 December 2014 #Purpose: This program analyze the directory structure of a Linux disk + and identify any files larger than 500 kbytes # $path = shift || '.'; read_dir($path); sub read_dir { $dir = shift; opendir (DH, $dir) or die "Couldn't open current directory: $! +"; while ($file = readdir(DH)) {#print "$file\n"; if ($file eq "." or $file eq "..") { next; } elsif (-z $file) { next; } elsif (-r $file and -f $file) { $size = -s $file; print $file," ",$size, "\n" if $size > 512000; } #recursion doesn't work i don't know why? # elsif (-d $file) # { # read_dir($file); # } } closedir DH; }

Replies are listed 'Best First'.
Re: Hi Monks could you pls help Perl dummy user
by roboticus (Chancellor) on Dec 17, 2014 at 01:38 UTC

    sibyurik:

    To illustrate what the Anonymous Monk above posted, here's a pair of functions, one of which is using a global (funky), and the other a local (monkey):

    use strict; use warnings; my $str1=''; sub funky { my $count = shift; return if $count > 5; $str1 = 4*$count; my $indent = "funky" . " "x$count; print $indent,"before recurse: count=$count, str1=$str1\n"; funky($count+1); print $indent,"after recurse: count=$count, str1=$str1\n"; } sub monkey { my $count = shift; return if $count > 5; my $str = 4*$count; my $indent = "monkey" . " "x$count; print $indent,"before recurse: count=$count, str=$str\n"; monkey($count+1); print $indent,"after recurse: count=$count, str=$str\n"; } funky(0); monkey(0);

    As you can see in the results below, the global variable $str1 got whacked, so has the same value after recursion for each level. The local value, however, retains its value, so can continue. The same thing is happening with your directory handle from readdir: When you recurse, you've clobbered the value, so you can't continue from that point. In fact, when the lowest level if your function is done, the directory handle is reporting "Nope, no more files" for each level on return.

    $ perl recurse.pl funkybefore recurse: count=0, str1=0 funky before recurse: count=1, str1=4 funky before recurse: count=2, str1=8 funky before recurse: count=3, str1=12 funky before recurse: count=4, str1=16 funky before recurse: count=5, str1=20 funky after recurse: count=5, str1=20 funky after recurse: count=4, str1=20 funky after recurse: count=3, str1=20 funky after recurse: count=2, str1=20 funky after recurse: count=1, str1=20 funkyafter recurse: count=0, str1=20 monkeybefore recurse: count=0, str=0 monkey before recurse: count=1, str=4 monkey before recurse: count=2, str=8 monkey before recurse: count=3, str=12 monkey before recurse: count=4, str=16 monkey before recurse: count=5, str=20 monkey after recurse: count=5, str=20 monkey after recurse: count=4, str=16 monkey after recurse: count=3, str=12 monkey after recurse: count=2, str=8 monkey after recurse: count=1, str=4 monkeyafter recurse: count=0, str=0

    Update: Immediately after posting, I realize that I didn't need two functions to illustrate it, the count variable is already localized, so the first function was enough. Ah, well.

    ...roboticus

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

Re: Hi Monks could you pls help Perl dummy user
by Anonymous Monk on Dec 17, 2014 at 01:15 UTC
    recursion doesn't work i don't know why?

    Because your read_dir is not safe to use for recursion - $dir and all the other variables in the sub are global. You need to use lexical variables, for example my $dh instead of DH, to make them local to the blocks they are defined in. Using warnings and strict (use warnings; use strict;) will help you with this and many other potential problems.

    without fancy module

    Why? File::Find is in the core.

    use File::Find; find( sub { return unless -r && -f; my $size = -s; print "$File::Find::name $size\n" if $size > 51200; }, $path );
      > Using warnings and strict (use warnings; use strict;) will help you with this and many other potential problems.

      unfortunately do neither use strict nor use warnings complain about bareword filehandles, and nowadays I wonder why.

      They don't have an explicit package name and localizing with a glob local *FH isn't trivial.

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

        That's output for my program that doesn't go into any directories. Do you know why?

        yura@yura:~$ ls -a . .bashrc dir_tree .face +.goutputstream-51G14W .ICEauthority .mixxx Pictures .pu +lse-cookie Templates .xsession-errors.old .. .cache .dmrc .gconf +.goutputstream-F8CZ4W .java Mixxx .profile .Sk +ype Videos .adobe .compiz Documents .gnome2 +.goutputstream-TBVW4W java_progs module project .ss +h .viminfo .apport-ignore.xml .config Downloads .gnome2_private +.goutputstream-Z89K4W .local .mozilla project_final .sw +t workspace .bash_history .dbus .eclipse .goutputstream-11KV4W +.gstreamer-0.10 .macromedia Music Public sys +err.log .Xauthority .bash_logout Desktop examples.desktop .goutputstream-1UX14W +.gtk-bookmarks .mission-control perl .pulse sys +out.log .xsession-errors yura@yura:~$ perl dir_tree .ICEauthority 33170 module 433 project_final 4515 dir_tree 704 .profile 675 project 4486 sysout.log 19807 examples.desktop 8445 syserr.log 2350 .pulse-cookie 256 .xsession-errors.old 828 .viminfo 14093 .bash_history 17965 .face 9447 .bashrc 3637 .bash_logout 220 yura@yura:~$

      I used strict and warnings but it doesn't go into any other directories other than current. Thus recursion doesn't work correctly i guess. Could you pls help me tofix it now?

      #!/usr/bin/perl # #Author: Yury Sibirski #Name: users_home_dir #Date: 16 December 2014 #Purpose: This program analyze the directory structure of a Linux disk + and identify any files larger than 500 kbytes # use strict; use warnings; my $path = shift || '.'; read_dir($path); sub read_dir { my $dir = shift; opendir (my $DH, $dir) or die "Couldn't open current directory +: $!"; while (my $file = readdir($DH)) {#print "$file\n"; if ($file eq "." or $file eq "..") { next; } elsif (-z $file) { next; } elsif (-r $file and -f $file) { my $size = -s $file; print $file," ",$size, "\n" if $size > 200; } elsif (-d $file) { read_dir($file); } } closedir $DH; }
        works for me!

        Cheers Rolf

        (addicted to the Perl Programming Language and ☆☆☆☆ :)

      This 1000 times. Beginners guide to File::Find has a nice simple explanation on how to use it. The code that you have written and commented out is potentially dangerous as it will blindly follow symlinks. Since you're on Linux, this is a very real concern.

      It gives me an error like no &wanted subroutine given at /usr/share/perl/5.18/File/Find.pm line 1073. NO IDEA WHY?

      #!/usr/bin/perl use File::Find; use strict; use warnings; my $path = shift || '.'; find($path); find( sub { return unless -r && -f; my $size = -s; print "$File::Find::name $size\n" if $size > 51200; }, $path )
Re: Hi Monks could you pls help Perl dummy user
by Anonymous Monk on Dec 17, 2014 at 09:20 UTC
    use strict; use warnings; recdir( shift || '.' ); exit 0; sub recdir { my ($dir) = @_; opendir my $dh, $dir or die $!; while ( my $file = readdir $dh ) { next if $file eq '.' or $file eq '..'; my $full_name = "$dir/$file"; if ( -x -r -d $full_name ) { recdir($full_name); } elsif ( -r -f _ ) { my $size = -s _; next if $size < 500; print $full_name, ' ', $size, "\n"; } } }
      while ( my $file = readdir $dh ) {
      Come to think of it, should probably be
      while ( defined( my $file = readdir $dh ) ) {
        No no, it has to have five defined , like this
        while ( defined defined defined defined defined( my $file = readdir $d +h ) ) {

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1110583]
Approved by Athanasius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (3)
As of 2024-04-19 19:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found