【问题标题】:How can I compare two text files line by line and print error if not matched?如果不匹配,如何逐行比较两个文本文件并打印错误?
【发布时间】:2014-07-31 08:44:18
【问题描述】:

让我简要介绍一下我想做的事情,因为现在我的脚本正在将文件从 SFTP 拉到本地系统。确保文件在拉取时不会损坏。所以我需要确保file size 完全相同。从 SFTP 提取文件后,我将file sizefilename 打印到filename.txt,如下所示。我这样做是因为我尝试比较这两个文本文件以确保没有文件损坏。

文件名.txt

7 hankeong_test.txt
3 hankeong_test2.txt
10753 hankeong_test3.txt

但是,SFTP 命令是有限的。它不能只显示SizeFile name,我唯一可以使用的命令是ls -l *.txt。下面是从SFTP到input.txt的输出。

input.txt

-rwxr-xr-x     512      501             7 Jul 24 17:54 hankeong_test.txt
-rwxr-xr-x     512      501             3 Jul 25 11:32 hankeong_test2.txt
-rwxr-xr-x     512      501         10753 Jul 24 17:54 hankeong_test3.txt
sftp> ls -l *.txt
sftp> quit

当这两个文件有两种不同的格式时,如何比较它们?

预期输出:

代码可以逐行比较两个文件,看看行是否正确,如果不正确会打印出ERROR消息给用户。

我正在使用 Windows 7 和 SSH 技术访问 SFTP。

有什么建议或其他更好的解决方案可以分享吗?谢谢!

【问题讨论】:

  • 你考虑过使用 diff
  • 在您的问题中值得一提的是您在本地使用什么操作系统以及您可以使用哪些访问远程系统的方法。从您之前的屏幕截图来看,您似乎在本地计算机上运行 Windows。
  • @TomFenech 抱歉,由于时区问题,回复晚了。我正在使用 Windows 7 和 SSH 技术访问 SFTP。
  • @RussHyde Nop,我还是 perl 新手,这就是为什么我对它还不太了解。我将看看差异。感谢您的建议。

标签: perl


【解决方案1】:

一般来说,解析ls 并不是一个好主意:例如,参见this question。也就是说,您可以使用类似这样的方法来比较两个列表:

use strict;
use warnings;
use autodie;

my ($files, $ls) = ($ARGV[0], $ARGV[1]);
open my $fh_files, "<", $files;
open my $fh_ls, "<", $ls;

my %sizes;
while (<$fh_files>) {    
    # regex assumes filenames contain no spaces
    if (my ($size, $name) = /^(\d+)\s+(\S+)$/) {
        $sizes{$name} = $size;
    }
}

while(<$fh_ls>) {
    # if output is tab-delimited, use split /\t/
    my @cols = split;
    my ($size, $name) = ($cols[3], $cols[7]);

    if (!defined $sizes{$name}) { 
        print "$name: file exists locally but not on device\n";
    }
    elsif ($sizes{$name} != $size) {
        print "$name has incorrect size\n";
        print "size on host: $size\n";
        print "local size: $sizes{$name}\n";
    }
}

close $fh_files;
close $fh_ls;

像这样使用它:perl filelist_compare.pl Filename.txt input.txt

【讨论】:

  • 谢谢汤姆,看来这是我设法理解的唯一解决方案,这与我尝试做的完全一样。谢谢!向你致敬o.o\!
【解决方案2】:

至少有两种更好的方法:

  1. 使用rsync 代替SFTP 传输并检查本地和远程文件是否相同。

  2. 使用一些用于 SFTP 的 Perl 模块执行传输(例如,Net::SFTP::Foreign)。您将能够在发生传输错误时进行处理,并轻松查询远程文件系统。

【讨论】:

  • 同意这两种方法中的任何一种都更可取。或许一些关于如何在 Perl 中进行传输的示例会很有用?
【解决方案3】:

我敢说使用 MD5 或 SHA 哈希或 unix sum 命令来确定文件的有效性吗?

【讨论】:

  • 比较哈希听起来是个好主意。或许您可以向 OP 提供一些关于他们如何执行此操作的想法?
【解决方案4】:

我建议使用文件的 md5 摘要而不是文件大小。如果您具有 sftp 访问权限,则您可能还具有 ssh 访问权限。如果是这样,请在远程服务器上尝试以下操作,并在本地尝试相同操作。将输出保存在两个文件中,然后与diff进行比较:

openssl md5 *.txt
MD5(hankeong_test.txt)= 0bee89b07a248e27c83fc3d5951213c1
MD5(hankeong_test2.txt)= 614dd0e977becb4c6f7fa99e64549b12
MD5(hankeong_test3.txt)= b6273b589df2dfdbd8fe35b1011e3183

【讨论】:

    猜你喜欢
    • 2017-07-30
    • 1970-01-01
    • 2014-08-28
    • 2014-01-08
    • 2016-10-23
    • 2012-02-18
    • 1970-01-01
    • 2021-06-26
    • 2016-07-30
    相关资源
    最近更新 更多