Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

how to get total numbers of files in a directory?

by hweefarn (Acolyte)
on Dec 09, 2003 at 13:09 UTC ( [id://313405] : perlquestion . print w/replies, xml ) Need Help??

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

hi :) i just join this group and this is my first posting. i would like to ask about how can i get the total of files in a spesific directory? for example, i want to know there are how many files in directory /home/a. if can, i want to count all text file (.txt) only. thank you very much :) regards, hweefarn
  • Comment on how to get total numbers of files in a directory?

Replies are listed 'Best First'.
Re: how to get total numbers of files in a directory?
by PodMaster (Abbot) on Dec 09, 2003 at 13:23 UTC
      And some examples of usage

      File::Find::Rule

      use File::Find::Rule; my $cnt = find( file => name => "*.txt", maxdepth => 1, in => "/home/a" );
      glob - Update: fixed bug as noted by sauoq below (it was originally going to be @{ [ glob "*.txt" ] }, that'll teach me for posting in a hurry :)
      my $cnt = () = glob "/home/a/*.txt";
      opendir, readdir + grep
      opendir( my $d, "/home/a" ) or die "ack: $!"; my $cnt = grep { -f and /\.txt$/ } readdir $d;
      HTH

      _________
      broquaint

        my $cnt = glob "/home/a/*.txt";

        Unfortunately, no. It would be more intuitive that way, but the real behavior of that is to set $cnt to the first filename in the list of exansions.

        $ touch {a,b,c}.txt; perl -le 'my $c = glob "*.txt"; print $c' a.txt
        The clunky fix is to force list context...
        $ touch {a,b,c}.txt; perl -le 'my $c =()= glob "*.txt"; print $c' 3

        -sauoq
        "My two cents aren't worth a dime.";
        
Re: how to get total numbers of files in a directory?
by gjb (Vicar) on Dec 09, 2003 at 13:51 UTC

    Since you seem to work on a Un*x system you could also simply resort to command line tools that are quite up to this task. (That is, if you're only after the result of what you ask about.)

    find /home/a -type f -name "*.txt" | wc -l
    would do nicely, although it would count recursively, i.e. it would also count text files in subdirectories. If you want to limit the count to the specified directory, modify the above to read:
    find /home/a -type f -name "*.txt" -maxdepth 0 | wc -l

    The /home/a is the directory you want to search, -type f specifies that you're only interested in files, -name "*.txt" implies that you only want files that have a .txt suffix, -maxdepth 0 specifies that you want 0 levels of recursion, i.e. you want find to limit itself to the directory specified.

    Learning how to use find definitely pays off, see the relevant man page for more info since it is really very powerful, especially when using the -exec flag.

    Hope this helps, -gjb-

      Easier method for one directory is ofcourse
      ls /home/a/*.txt |wc -l
      But learning find is definedly worth it as well :).

      UPDATE:
      Duh, was *.txt. Double duh, ls goes wild if dir name matches as well, so be careful. Find tends to be easier to keep under control :P.
        to avoid ls wildness and to get a true listing of all files ( some versions of ls, like hp-ux, put multiple files on one line ) do ls -ald /home/a/*.txt | wc -l And Find is also your Friend.
      -maxdepth is not implemented on all versions of find. beware. a suitable replacement for getting the number of *.txt files in the current directory is  ls | egrep '\.txt$' |wc -l with the caveat that directory names that end in .txt will be falsely listed in the count.


      -Waswas
        This would miss hidden files. Maybe ls -lad *.txt | grep -v ^d | wc -l would be a better solution.

        /dev/null
Re: how to get total numbers of files in a directory?
by delirium (Chaplain) on Dec 09, 2003 at 13:43 UTC
    This code should do what you want:

    perl -le 'print scalar @{[</home/a/*.txt>]}'

    Welcome to the forum!

      Watch out for dirctories ending in .txt
      $ touch temp.txt $ mkdir dir.txt $ perl -le 'print scalar @{[<./*.txt>]}' 2
      Try this:
      $ perl -le 'print scalar @{[grep {-f} <./*.txt>]}' 1

      --

      flounder

Re: how to get total numbers of files in a directory?
by kodo (Hermit) on Dec 09, 2003 at 14:19 UTC
    As stated in perldoc perlport it's better to not use globbing, instead use opendir.

    code-example (untested) for your issue would be:
    opendir(DIR, '/home/a') or die "couldn't opendir /home/a: $!"; while (local $_ = readdir(DIR)) { next unless $_ =~ /\.txt$/; print "$_\n"; } closedir(DIR) or die "couldn't close /home/a: $!";
    greetings
      I'd have written that as
      opendir(DIR, "/home/a") || die "can't open dir: $!"; my $count = grep(/\.txt$/, readdir(DIR)); closedir(DIR); print "There are $count .txt files\n";
      assuming that the only purpose is to get a count of matching files.

      Michael

        That has the disadvantage of potentially using a lot of memory if there are many files in the directory (the globbing solutions, and solutions that use readdir in list context all suffer from this).

        I would use something like:

        my $cnt = 0; local $_; chdir "/home/a" or die "chdir: $!"; opendir my $dh => "." or die "opendir: $!"; -f && /\.txt$/ && $cnt ++ while defined ($_ = readdir $dh); closedir $dh;

        Abigail

Re: how to get total numbers of files in a directory?
by Limbic~Region (Chancellor) on Dec 09, 2003 at 15:25 UTC
    hweefarn,
    As you can see, there are many ways to do it. Some of them do not involve Perl at all. I feel that it is worth while to point out that you can use shortcuts when you know your data. If you are not 100% sure of your data, then you need to take a little longer. Consider for instance that you have a directory called /home/a/blah.txt and you only want to count text files, not directories.
    #!/usr/bin/perl -w use strict; my $total; for ( glob ('/home/a/*.txt') ) { $total++ if ! -d; } print "The total is $total\n";
    Of course, this will only skip directories. If you want to avoid other kinds of files, you should take a look at perldoc -f -X. Welcome to The Monastery.

    Cheers - L~R

Re: how to get total numbers of files in a directory?
by Roger (Parson) on Dec 09, 2003 at 22:44 UTC
    There is always another way to do it. ;-)

    The following is my method that works on Unix/Linux platforms. It relies on the properties of -F switch of ls
    that appends a '/' character after directories, a '*' character after executables, etc.
    use strict; use warnings; use Data::Dumper; my @txt_files = map {m!(.*\.txt)[^/]*$!} split /\n/, `ls -F`; # ^txt only ^want non-directories # and throw away the flag print Dumper(\@txt_files); my $num_files = $#txt_files + 1;
Re: how to get total numbers of files in a directory?
by bigtiny (Acolyte) on Dec 10, 2003 at 20:35 UTC
    Not very elegant, but: $filecount = 0; @filesindir = `ls /home/a/*.txt`; foreach $file (@filesindir) { $filecount++; } print "The number of text files in my directory is: $filecount\n";
Re: how to get total numbers of files in a directory?
by bigtiny (Acolyte) on Dec 10, 2003 at 20:38 UTC

    Not very elegant, but:

    $filecount = 0; @filesindir = `ls /home/a/*.txt`; foreach $file (@filesindir) { $filecount++; } print "The number of text files in my directory is: $filecount\n";