http://qs1969.pair.com?node_id=479800

I was looking for a quick way to scan a directory and subdirectories for valid image files without relying on the file extension to identify image type.

This reads small chunk of each file and identifies images by header info.

Looking for code review/suggestions. As mentioned in threads bellow, this is work is for educational purposes.

zzSPECTREz

updates

Please read following threads to be aware of limitations and possible bugs.

  • Changed !/^\.{1,2}$/ to !/^\.{1,2}\z/ to hopefully eliminate the problem with filenames name: "..\n".

use strict; use warnings; sub read_dir { my $dir = shift; if ( opendir( DIR, $dir ) ) { my @tmp = readdir(DIR); my @files = map { "$dir/$_" } grep { !/^\.{1,2}\z/ && -f "$dir +/$_" } @tmp; my @dirs = map { "$dir/$_" } grep { !/^\.{1,2}\z/ && -d "$dir +/$_" } @tmp; closedir( DIR ); return ( \@files, \@dirs ); }else{ return; } } sub glob_files { my ($dir, $recurse) = @_; my @files; if ($dir) { my ($files, $dirs) = read_dir($dir) or return; if (@$files) { push @files, @$files; } recursion: { last unless $recurse; while (@$dirs) { my $d = shift (@$dirs); my @f = glob_files("$d", 1); push @files, @f; } } return @files; }else{ return; } } sub find_images { my @files = @_; my $file; my @images; foreach $file (@files) { open FH, $file or die "Error opening [$file]: $!\n"; my $data; my $type; next unless ( -s $file > 9 ); read(FH, $data, 10) or die "Error reading from [$file]: $!\n"; if ( $data =~ /^BM/ ) { $type = 'BMP'; }elsif ( $data =~ /^GIF8[79]a/) { $type = 'GIF'; }elsif ( $data =~ /^\xFF\xD8/ ) { $type = 'JPG'; }else { $type = undef; } push @images, ( [ $file, $type ] ) if ($type); close FH or die "Error closing file [$file]: $!\n"; } return @images if ( scalar (@images) ); return; } my (@files, @images); my $recurse = 1; my $verbose = 1; my $dir = '.'; @files = glob_files($dir, $recurse); @images = find_images(@files); if (@images){ foreach my $a (@images) { if ($verbose){ print "Found [",$a->[0],"] which appears to be an image of + type ",$a->[1],".\n"; }else{ print $a->[0],"\n"; } } } if ($verbose) { print "\n\tFound ", scalar(@files), " files."; print "\n\tFound ", scalar(@images), " images.\n"; }