下面是我的尝试,并将文本文件中的所有文件名加载到一个数组中,并将该数组与位于单独目录中的文件名进行比较。我想确定目录中的文件名而不是文件中的文件名,以便我可以处理这些文件。我能够成功加载两个目录的内容,但比较操作输出的所有文件不仅仅是差异。
提前感谢您的帮助。
use File::Copy;
use Net::SMTP;
use POSIX;
use constant DATETIME => strftime("%Y%m%d", localtime);
use Array::Utils qw(:all);
use strict;
use warnings;
my $currentdate = DATETIME;
my $count;
my $ErrorMsg = "";
my $MailMsg = "";
my $MstrTransferLogFile = ">>//CFVFTP/Users/ssi/Transfer_Logs/Artiva/ARTIVA_Mstr_Transfer_Log.txt";
my $DailyLogFile = ">//CFVFTP/Users/ssi/Transfer_Logs/Artiva/ARTIVA_Daily_Transfer_Log_" . DATETIME . ".txt";
my $InputDir = "//CFVFTP/Users/ssi/Transfer_Logs/folder1/";
my $MoveDir = "//CFVFTP/Users/ssi/Transfer_Logs/folder2/";
my $filetouse;
my @filetouse;
my $diff;
my $file1;
my $file2;
my %diff;
open (MSTRTRANSFERLOGFILE, $MstrTransferLogFile) or $ErrorMsg = $ErrorMsg . "ERROR: Could not open master transfer log file!\n";
open (DAILYLOGFILE, $DailyLogFile) or $ErrorMsg = $ErrorMsg . "ERROR: Could not open daily log file!\n";
#insert all files in master transfer log into array for cross reference
open (FH, "<//CFVFTP/Users/ssi/Transfer_Logs/Artiva/ARTIVA_Mstr_Transfer_Log.txt") or $ErrorMsg = $ErrorMsg . "ERROR: Could not open master log file!\n";
my @master = <FH>;
close FH;
print "filenames in text file:\n";
foreach $file1 (@master) { print "$file1\n"; }
print "\n";
#insert all 835 files in Input directory into array for cross reference
opendir (DIR, $InputDir) or $ErrorMsg = $ErrorMsg . "ERROR: Could not open input directory $InputDir!\n";
my @list = grep { $_ ne '.' && $_ ne '..' && /\.835$/ } readdir DIR;
close(DIR);
print "filenames in folder\n";
foreach $file2 (@list) { print "$file2\n"; }
print "\n";
#get the all files in the Input directory that are NOT in the master transfer log and place into @filetouse array
@diff{ @master }= ();;
@filetouse = grep !exists($diff{$_}), @list;;
print "difference:\n";
foreach my $file3 (@filetouse) { print "$file3\n"; }
print DAILYLOGFILE "$ErrorMsg\n";
print DAILYLOGFILE "$MailMsg\n";
close(MSTRTRANSFERLOGFILE);
close(DAILYLOGFILE);
这是输出的样子:
filenames in text file:
160411h00448car0007.835
filenames in folder
160411h00448car0007.835
160411h00448car0008.835
160418h00001com0001.835
difference:
160411h00448car0007.835
160411h00448car0008.835
160418h00001com0001.835
答案 0 :(得分:1)
这可以帮助您做您需要的事情。它将INPUT_DIR
中所有文件的名称存储为散列%files
中的键,然后删除LOG_FILE
中找到的所有名称。其余部分打印
此程序使用autodie
,因此无需显式检查IO操作是否成功。它首次在v5.10.1中的Perl 5核心中提供
use strict;
use warnings 'all';
use v5.10.1;
use autodie;
use feature 'say';
use constant LOG_FILE => '//CFVFTP/Users/ssi/Transfer_Logs/Artiva/ARTIVA_Mstr_Transfer_Log.txt';
use constant INPUT_DIR => undef;
chdir INPUT_DIR;
my %files = do {
opendir my $dh, '.';
my @files = grep -f, readdir $dh;
map { $_ => 1 } @files;
};
my @logged_files = do {
open my $fh, '<', LOG_FILE;
<$fh>;
};
chomp @logged_files;
delete @files{@logged_files};
say for sort keys %files;
经过大量磨损后,我发现原始代码
use strict;
use warnings 'all';
use v5.10.1;
use autodie;
use feature 'say';
use Time::Piece 'localtime';
use constant DATETIME => localtime()->ymd('');
use constant XFR_LOG => '//CFVFTP/Users/ssi/Transfer_Logs/Artiva/ARTIVA_Mstr_Transfer_Log.txt';
use constant DAILY_LOG => '//CFVFTP/Users/ssi/Transfer_Logs/Artiva/ARTIVA_Daily_Transfer_Log_' . DATETIME . '.txt';
use constant INPUT_DIR => '//CFVFTP/Users/ssi/Transfer_Logs/folder1/';
use constant MOVE_DIR => '//CFVFTP/Users/ssi/Transfer_Logs/folder2/';
chdir INPUT_DIR;
my @master = do {
open my $fh, '<', XFR_LOG;
<$fh>;
};
chomp @master;
my @list = do {
opendir my $dh, '.';
grep -f, readdir $dh;
};
my %diff;
@diff{ @master } = ();
my @filetouse = grep { not exists $diff{$_} } @list;
如您所见,它与我的解决方案非常相似。以下是关于原始
的一些注意事项始终使用词法文件句柄。对于open FH, ...
,文件句柄是全局,除非您明确地或直到程序终止,否则永远不会关闭。相反,open my $fh, ...
离开perl以关闭当前块末尾的文件句柄
始终使用open
的三参数形式,以便打开模式与文件名分开,并且永远不要将打开模式作为文件名的一部分。您打开了两次相同的文件:一次为$MstrTransferLogFile
,以>>
开头,一次明确,因为您需要读取权限
程序很少能够从IO操作错误中恢复。除非您正在编写故障安全软件,否则无法打开或读取文件或目录意味着该程序将无法实现其目的。这意味着没有理由积累错误消息列表 - 代码只有die
才能成功
如果您需要处理目录,readdir
的输出非常混乱,因为它包含伪目录.
和..
。但是如果你只想要文件,那么一个简单的grep -f, readdir $dh
将为你抛出这些文件
grep的块形式通常更具可读性,not
比!
更明显。因此grep !exists($diff{$_}), @list
更加清晰,因为grep { not exists $diff{$_} } @list
除非您的代码真的奇怪,否则评论通常会增加更多的噪音和混乱,并使结构模糊不清。让你的代码看起来像它的代码,所以你不必解释它
哦,不要在开始时把你可能需要的所有东西扔进去“以防万一”。编写代码,好像它就在那里,编译器会告诉你缺少什么
我希望有帮助
答案 1 :(得分:0)
首先,使用哈希来存储已处理的文件。然后,只需检查散列中是否存在文件。
(我已经更改了一些变量名称以使答案更清晰。)
foreach my $file (@dir_list) {
push @to_process, $file unless ($already_processed{$file});
}
(这可能是一个单行,但首先要以最扩展的形式工作。)
如果你坚持你的阵列,这看起来效率低得多
foreach my $file (@dir_list) {
push @to_process, $file unless (grep (/^$file$/, @already_processed));
}
(再次可能是一个单行,但......)