How can I use Perl to get a SHA1 hash of a file from the Windows command line?
I have a file called secure.txt in c:\temp. I want to run a Perl c开发者_如何学JAVAommand from the command line to print the SHA1 hash of secure.txt. I'm using ActivePerl 5.8.2. I have not used Perl before, but it's the most convenient option available right now.
perl -MDigest::SHA1=sha1_hex -le "print sha1_hex <>" secure.txt
The command-line options to Perl are documented in perlrun. Going from left to right in the above command:
-MDigest::SHA1=sha1_hex
loads the Digest::SHA1 module at compile time and importssha1_hex
, which gives the digest in hexadecimal form.-l
automatically adds a newline to the end of anyprint
-e
introduces Perl code to be executed
The funny-looking diamond is a special case of Perl’s readline
operator:
The null filehandle
<>
is special: it can be used to emulate the behavior ofsed
andawk
. Input from<>
comes either from standard input, or from each file listed on the command line. Here's how it works: the first time<>
is evaluated, the@ARGV
array is checked, and if it is empty,$ARGV[0]
is set to"-"
, which when opened gives you standard input. The@ARGV
array is then processed as a list of filenames.
Because secure.txt
is the only file named on the command line, its contents become the argument to sha1_hex
.
With Perl version 5.10 or later, you can shorten the above one-liner by five characters.
perl -MDigest::SHA=sha1_hex -E 'say sha1_hex<>' secure.txt
The code drops the optional (with all versions of Perl) whitespace before <>
, drops -l
, and switches from -e
to -E
.
-E commandline
behaves just like
-e
, except that it implicitly enables all optional features (in the main compilation unit). Seefeature
.
One of those optional features is say
, which makes -l
unnecessary.
say FILEHANDLE LIST
say LIST
say
Just like
say LIST
is simply an abbreviation for{ local $\ = "\n"; print LIST }
This keyword is only available when the
say
feature is enabled: seefeature
.
If you’d like to have this code in a convenient utility, say mysha1sum.pl
, then use
#! /usr/bin/perl
use warnings;
use strict;
use Digest::SHA;
die "Usage: $0 file ..\n" unless @ARGV;
foreach my $file (@ARGV) {
my $sha1 = Digest::SHA->new(1); # use 1 for SHA1, 256 for SHA256, ...
$sha1->addfile($file);
say($sha1->hexdigest, " $file");
}
This will compute a digest for each file named on the command line, and the output format is compatible with that of the Unix sha1sum
utility.
C:\> mysha1sum.pl mysha1sum.pl mysha1sum.pl
8f3a7288f1697b172820ef6be0a296560bc13bae mysha1sum.pl
8f3a7288f1697b172820ef6be0a296560bc13bae mysha1sum.pl
You didn’t say whether you have Cygwin installed, but if you do, sha1sum
is part of the coreutils package.
Try the Digest::SHA module.
C:\> perl -MDigest::SHA -e "print Digest::SHA->new(1)->addfile('secure.txt')->hexdigest"
As of this writing, both Strawberry Perl and ActiveState Perl include the shasum
command that comes with Digest::SHA. If you chose the default options during setup, this will already be in your %PATH%
.
If you really, really want to write your own wrapper for Digest::SHA, the other answers here are great.
If you just want to "use Perl" to get the SHA1 hash for a file, in the sense that you have ActiveState Perl, and it comes with the shasum
command-line utility, it's as simple as:
shasum secure.txt
The default hashing algorithm is SHA1; add -a1
if you want to be explicit (not a bad idea).
The default output format is the hash, two spaces, then the filename. This is the same format as sha1sum
and similar utilities, commonly found on Unix/Linux systems. If redirected into a file, that filename can be given to shasum -c
later in order to verify the integrity whatever files you had hashed previously.
If you really, really don't want to see the filename, just the SHA1 hash, either of these will chop off the filename part:
Using Powershell:
shasum secure.txt | %{$_split()[0]}
Using Command Prompt (old-school batch scripting):
for /f %i in ('shasum secure.txt') do echo %i
For the second one, make sure you use %%i
instead of %i
(both places) if you're putting that in a .cmd
or .bat
file.
Use Digest::SHA1
like so:
Using the OO strategy:
#!/usr/bin/perl -w
use v5.10; # for 'say'
use strict;
require Digest::SHA1;
my $filename = 'secure.txt';
my $sha1 = Digest::SHA1->new->addfile($filename)->hexdigest;
say $sha1;
Note that calling ->hexdigest
causes the object's state to clear, causing the current digest it's calculating to be destroyed. You can re-use the $sha1
object at that point.
You can also use sha1_hex
sub on the file contents:
#!/usr/bin/perl -w
use strict;
use Digest::SHA1 qw/ sha1_hex /;
my $filename = "secure.txt";
# open file
open my $fhi, '<', $filename or die "Cannot open file '$filename' for reading: $!";
# slurp all the file contents
my $file_contents;
{local $/; $file_contents = <$fhi>;}
close $fhi;
print &sha1_hex($file_contents);
Note that you can use Digest::SHA
instead, where new()
takes the algorithm to use as parameter (e.g. 1 for SHA1, 256 for SHA256, ...):
require Digest::SHA;
my $sha1 = Digest::SHA->new(1)->addfile($filename)->hexdigest();
精彩评论