in reply to Re: File ext number
in thread File ext number

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.

Replies are listed 'Best First'.
Re^3: File ext number
by Lady_Aleena (Priest) on Mar 20, 2010 at 04:34 UTC

    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 };