Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re: File ext number

by Lady_Aleena (Priest)
on Mar 20, 2010 at 01:13 UTC ( [id://829740]=note: print w/replies, xml ) Need Help??


in reply to File ext number

Here is a more verbose solution and assumes that your files are being stored in an array. In the following code, the array is named @files. I have only tested this on files which all have extensions.

my %extensions; for my $file (sort @files) { my @split = split(/\./,$file); my $key = $split[1]; my $num = 1; if (exists $extensions{$key}) { $extensions{$key} += $num; } else { $extensions{$key} = $num; } } while (my ($key,$value) = each %extensions) { print $key." - ".$value."\n"; }
Have a nice day!
Lady Aleena

Replies are listed 'Best First'.
Re^2: File ext number
by ikegami (Patriarch) on Mar 20, 2010 at 03:13 UTC

    Here is a more verbose solution and assumes that your files are being stored in an array.

    Not really.

    for my $file (sort grep -f, readdir $dh)
    works just as well as
    for my $file (sort @files)

    my $num = 1; is useless and detrimental. It reminds me of

    use constant TWO => 2;

    when one should rather be doing

    use constant NUM_EYES => 2;

    There's a point where constants become a hindrance.

    my $num = 1; if (exists $extensions{$key}) { $extensions{$key} += $num; } else { $extensions{$key} = $num; }
    should be
    if (defined $extensions{$key}) { $extensions{$key} += 1; } else { $extensions{$key} = 1; }
    But why not just use ++? It even works great at incrementing previously undefined values.
    ++$extensions{$key};

      I had made the assumption that the files were being stored in an array. I hadn't thought of any other way to get the file list from the directory outside of File::Find which creates an array.

      I really overdid counting the instances of each file extension. I had thought of incrementation, but I hadn't thought to use it to define a previously undefined variable. So, the code below is better without the constant my $num = 1;.

      my %extensions; for my $file (sort @files) { my @split = split(/\./,$file); my $key = $split[1]; ++$extensions{$key}; } while (my ($key,$value) = each %extensions) { print $key." - ".$value."\n"; }
      Have a nice day!
      Lady Aleena
Re^2: File ext number
by jwkrahn (Abbot) on Mar 20, 2010 at 03:49 UTC
    my @split = split(/\./,$file); my $key = $split[1];

    You are assuming that there is only one period in the file name.    That would probably be better as:

    my $key = ( split /\./, $file )[ -1 ];

    Or use File::Basename or File::Spec to get the extention.

      You are right, I made the assumption that there will only be one period in the file name. I have not seen all that many files with more than one period in their names. It may be because that I am a Windows user and have to to special lengths to see a file extension. The .htaccess file always looks odd on my file list.

      So to further refine the code, including previous refinements, it would be...

      my %extensions; for my $file (sort @files) { my @split = split(/\./,$file)[-1]; my $key = $split[1]; ++$extensions{$key}; } while (my ($key,$value) = each %extensions) { print $key." - ".$value."\n"; }
      Have a nice day!
      Lady Aleena
        my @split = split(/\./,$file)[-1];

        That will produce a syntax error:

        $ perl -e'my @split = split(/\./,$file)[-1];' syntax error at -e line 1, near ")[" Execution of -e aborted due to compilation errors.
        Hi Lady Aleena, we were talking in the CB about "list slice" as well as array indexing and specifically about using the -1 index value and I came across this post.
        One point is that the file test operators (like -f) take a full path. I always put that concept into the code even if the current path is ".", but that is tangential to the main point.
        Something like
           my @split = split(/\./,$file)[-1]; should probably be my ($last) = (split(/\./,$file))[-1];

        Anyway I was looking for a place to use split and -1 index. See below... Sometimes Perl doesn't like (@parts)[-1] and prefers $parts[-1]. But the array returned from any array returning function can be "sliced". In the code below, I could have written (split(/\./,$_))[-1] instead of (@parts)[-1] but of course that would split the input twice.

        I guess on other file system points that you may or may not know...in the file system itself, everything is a file, a directory is essentially just a special kind of file. So this -f test operator is a bit of a misnomer, it means give me all files which are not directory files - this excludes normal directories as well as the "." and ".." files.

        Windows will not let you make a file like ".abc", but that would be normal under Unix as is a convention meaning that this is a "hidden" file which normally should not be displayed. Yes Windows will allow you to make files with lots of "." characters in them as well as files which have no "."'s. If such a name exists Windows only cares about the the characters after the last ".".

        Anyway the below takes into account a Unix style file which starts with "." but is not a directory and also counts files which have no Windows style extensions. My C:/temp file as good test candidate as there is all sorts of junk in there!

        #!/usr/bin/perl -w use strict; use Data::Dumper; my $cur_dir_path = '.'; opendir (H, "$cur_dir_path") || die "unable to opendir $cur_dir_path"; my @extensions = map { my @parts = split(/\./,$_); @parts > 1 ? (@parts)[-1] : 'NONE' } grep{ -f "$cur_dir_path/$_"} readdir H; my %extension_counter; foreach (@extensions) { $extension_counter{$_}++ } print Dumper \%extension_counter; __END__ prints for my temp dir: $VAR1 = { 'sorted-txt' => 1, 'SCP' => 1, 'bin' => 1, 'db' => 3, 'txt' => 83, 'ini' => 1, 'dbi' => 1, 'h' => 1, 'jpg' => 1, 'dat' => 6, 'new' => 1, 'doc' => 4, 'stackdump' => 3, 'out' => 1, 'bat' => 3, 'script' => 1, 'NONE' => 21, 'pl' => 462, 'PL' => 1, 'c' => 13, 'zip' => 2, 'temp' => 1, 'cpp' => 1, 'exe' => 11 };

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2024-03-28 13:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found