如何在Windows命令行中使用Perl获取文件的SHA1哈希值?

8

我在 c:\temp 目录下有一个名为 secure.txt 的文件。我想从命令行运行 Perl 命令以打印 secure.txt 的 SHA1 哈希值。我正在使用 ActivePerl 5.8.2。虽然我之前没有使用过 Perl,但它是目前最方便的选项。


来自未来的问候!ActiveState和Strawberry Perl都包括Digest::SHA的shasum命令,如果你在安装过程中选择了默认选项,它应该已经是你的%PATH%。如果你真的,_真的_想为Digest::SHA编写自己的包装器,那么这里的其他答案都非常好。但是,如果你宁愿使用一个“标准”Perl模块提供的命令行工具,那么请参阅我的下面的答案。 - TheDudeAbides
4个回答

21
perl -MDigest::SHA1=sha1_hex -le "print sha1_hex <>" secure.txt
Perl的命令行选项在perlrun文档中有介绍。上面的命令从左到右依次是:
  • -MDigest::SHA1=sha1_hex会在编译时加载Digest::SHA1模块并导入sha1_hex,它以十六进制形式给出摘要。
  • -l自动在任何print输出的末尾添加一个换行符。
  • -e引入要执行的Perl代码。

奇怪的钻石符号是Perl的readline操作符的特殊情况:

空文件句柄<>是特殊的:它可以用于模拟sedawk的行为。来自<>的输入既可以来自标准输入,也可以来自命令行上列出的每个文件。这是它的工作原理: 第一次评估<>时,将检查@ARGV数组,如果为空,则将$ARGV[0]设置为"-",打开后给出标准输入。然后处理@ARGV数组作为文件名列表。

因为secure.txt是命令行中唯一命名的文件,所以它的内容成为了sha1_hex的参数。

使用Perl 5.10或更高版本,您可以将上述单行命令缩短五个字符。

perl -MDigest::SHA=sha1_hex -E 'say sha1_hex<>' secure.txt
代码在所有版本的Perl中都可以省略可选的(空格)<>,删除-l并从-e切换到-E
其中之一可选功能是say,它使-l变得不必要。 -E commandline的行为与-e完全相同,只是它会隐式启用所有可选功能(在主编译单元中)。参见featuresay FILEHANDLE LIST say LIST sayprint完全相同,但会隐式附加换行符。say LIST只是一个缩写。
  { local $\ = "\n"; print LIST }

只有在启用say功能时才能使用此关键字:请参见feature

如果您想将此代码放入一个方便的实用程序中,例如mysha1sum.pl,请使用以下命令:

#! /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");
}

这将为命令行上命名的每个文件计算一个摘要,输出格式与Unix sha1sum实用程序兼容。

C:\> mysha1sum.pl mysha1sum.pl mysha1sum.pl 
8f3a7288f1697b172820ef6be0a296560bc13bae  mysha1sum.pl
8f3a7288f1697b172820ef6be0a296560bc13bae  mysha1sum.pl

您并没有说您是否已经安装了Cygwin,但如果您已经安装了,sha1sum是coreutils包的一部分。


4
注意:由于secure.txt是唯一的文件,因此它的内容成为sha1_hex(每行一个单独参数)的参数。恰巧,sha1_hex将其参数重新连接在一起,并给出整个文件的SHA1值,但在其他地方使用<>未必会有同样的效果。 - ysth

7
尝试使用Digest::SHA模块。
C:\> perl -MDigest::SHA -e "print Digest::SHA->new(1)->addfile('secure.txt')->hexdigest"

0

截至本文撰写时,Strawberry PerlActiveState Perl都包含了Digest::SHA附带的shasum命令。如果您在安装过程中选择了默认选项,则此命令已经在您的%PATH%中。

如果您真的非常想要为Digest::SHA编写自己的包装器,那么这里的其他答案也很好。

如果您只是想要使用Perl来获取文件的SHA1哈希值,就像您已经拥有ActiveState Perl,并且它附带了shasum命令行实用程序一样,那么只需简单地执行以下操作:

shasum secure.txt

默认的哈希算法是SHA1;如果您想要明确指定,可以添加-a1(这不是一个坏主意)。

默认的输出格式是哈希值,两个空格,然后是文件名。这与sha1sum和类似工具的格式相同,通常在Unix/Linux系统中找到。如果将其重定向到文件中,稍后可以将该文件名提供给shasum -c,以验证之前已哈希的任何文件的完整性。

如果您真的,真的不想看到文件名,只想看到SHA1哈希值,可以使用以下任一方法截取文件名部分:

使用PowerShell:

shasum secure.txt | %{$_split()[0]}

使用命令提示符(老派批处理脚本):

for /f %i in ('shasum secure.txt') do echo %i

对于第二个,请确保在将其放入 .cmd.bat 文件中时,使用 %%i 而不是 %i(两个位置都要修改)。

-1

使用 Digest::SHA1 的方法如下:

使用面向对象的策略:

#!/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;

请注意,调用->hexdigest会导致对象的状态清除,从而破坏它正在计算的当前摘要。此时,您可以重新使用$sha1对象。
您还可以在文件内容上使用sha1_hex子程序:
#!/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);

请注意,您可以使用 Digest::SHA 替代,其中 new() 接受算法作为参数(例如 SHA1 为 1,SHA256 为 256 等):
require Digest::SHA;
my $sha1 = Digest::SHA->new(1)->addfile($filename)->hexdigest();

6
请使用本地词汇文件句柄 - open my $in_data, '<', 'secure.txt' or die ... - Ether
4
使用词法句柄有很好的理由。请参见https://dev59.com/wXM_5IYBdhLWcg3wNgKZ - daotoad
4
即使在不需要的时候,也要保持良好的习惯,这样当你需要时,它们就会成为习惯。 :) - brian d foy
有一种方法可以在不需要自己读取文件内容的情况下完成它。 - Brad Gilbert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接