3

Is there any way to write a Perl script to calculate the MD5sum of every file in a directory?

If so, how could I do this?

  • 1
    Get a list of the files in the directory. Read each one. Calculate the md5sum of the contents. Print it. – hobbs Oct 19 '13 at 00:50
  • How can I access the ls command from perl? SHould I read the contents of the list into an array? Then, is it possible to use the system's md5sum command on each filename stored in the array? –  Oct 19 '13 at 00:52

3 Answers3

5

Well there are many ways to do this but it comes down to two operations you need to preform. You will first need to locate a list of the files you would like to run the check and then you will need to run the md5sum check on each of those files. There is a ton of ways to do this but the following should work for your needs.

#!/usr/bin/perl

use strict;
use warnings;
use Digest::MD5 qw(md5_hex);

my $dirname = "/home/mgreen/testing/";
opendir( DIR, $dirname );
my @files = sort ( grep { !/^\.|\.\.}$/ } readdir(DIR) );
closedir(DIR);

print "@files\n";

foreach my $file (@files) {
    if ( -d $file || !-r $file ) { next; }
    open( my $FILE, $file );
    binmode($FILE);
    print Digest::MD5->new->addfile($FILE)->hexdigest, " $file\n";
    close($FILE);
}

The above will grab the md5sum for each file in the directory and skip any sub-directories and print it to STDOUT. The MD5 checksum part is then done by the Digest::MD5 module which is ultimately what I think you are looking for.

I do like your question though as it is open-ended with alot of possible solutions like all "How do I do this in perl?" questions so I am sure you will get alot of possible solutions and I will most likely update mine when I get home later.

MattSizzle
  • 3,145
  • 1
  • 22
  • 42
  • 1
    "The above will grab the md5sum for each file in the directory..." Aren't you calculating the md5sum for the file name and not the file? – Kenosis Oct 19 '13 at 01:52
  • 1
    It's usually better to use glob than angle brackets. – stark Oct 19 '13 at 02:15
  • @Kenosis you are correct and I modified the code. – MattSizzle Oct 19 '13 at 04:06
  • @stark yeah that is what I get for trying to answer in phone while on the bus. – MattSizzle Oct 19 '13 at 04:09
  • i just tried this and i cannot get it to print $FILE and $file unless i put this script in the root directory of the files. if i place this scripts in the root of C:/ then set the directory to the directory of the files i need to check, it will print @files, but will not print $FILE or $file – james28909 Dec 07 '13 at 23:33
  • @MattGreen how can i set this up so it will check each files MD5 against an array? – james28909 Dec 08 '13 at 16:38
  • 1
    @james28909 can you post it in a new question as a continuation of this question? There is additional details such as what is in the array that will be needed to answer properly. – MattSizzle Jun 30 '14 at 19:39
0

Maybe using find with -exec can do the job?

find . -name "*.*" -exec md5sum '{}' \; 

The '{}' will be replaced with the name of each file.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
0

Use opendir and readdir or other recursive method. Here is an example:

#!/usr/bin/perl -w
use warnings;
my $DIR_PATH="a";
opendir DIR, ${DIR_PATH} or die "Can not open \"$DIR_PATH\"\n";
@filelist = readdir DIR;


foreach $file (@filelist) {
  open(IN,"a/$file")or die "cannot open";
  while(<IN>){...}
  close IN;
}
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
YaleCheung
  • 630
  • 3
  • 9