我想列出目录中的文件n文件夹。这是此目录中文件的列表。
Output1.sv
Output2.sv
Folder1
Folder2
file_a
file_b
file_c.sv
但是其中一些我不希望将其列出。不包含文件的列表,我在input.txt中列出如下。注意:其中一些是文件,一些是文件夹
NOT_INCLUDED=file_a
NOT_INCLUDED=file_b
NOT_INCLUDED=file_c.sv
这是代码。
#!/usr/intel/perl
use strict;
use warnings;
my $input_file = "INPUT.txt";
open ( OUTPUT, ">OUTPUT.txt" );
file_in_directory();
close OUTPUT;
sub file_in_directory {
my $path = "experiment/";
my @unsort_output;
my @not_included;
open ( INFILE, "<", $input_file);
while (<INFILE>){
if ( $_ =~ /NOT_INCLUDED/){
my @file = $_;
foreach my $file (@file) {
$file =~ s/NOT_INCLUDED=//;
push @not_included, $file;
}
}
}
close INFILE;
opendir ( DIR, $path ) || die "Error in opening dir $path\n";
while ( my $filelist = readdir (DIR) ) {
chomp $filelist;
next if ( $filelist =~ m/\.list$/ );
next if ( $filelist =~ m/\.swp$/ );
next if ( $filelist =~ s/\.//g);
foreach $_ (@not_included){
chomp $_;
my $not_included = "$_";
if ( $filelist eq $not_included ){
next;
}
push @unsort_output, $filelist;
}
closedir(DIR);
my @output = sort @unsort_output;
print OUTPUT @output;
}
我想要的输出是列出该目录中的所有文件,但input.txt'NOT_INCLUDED'中的文件列表除外。
Output1.sv
Output2.sv
Folder1
Folder2
但是我得到的输出似乎仍然包含该不需要的文件。
答案 0 :(得分:2)
这部分代码没有意义:
while ( my $filelist = readdir (DIR) ) {
...
foreach $_ (@not_included){
chomp $_;
my $not_included = "$_";
if ( $filelist eq $not_included ){
next;
} # (1)
push @unsort_output, $filelist; # (2)
}
此代码包含三个大括号({
),但仅包含两个大括号(}
)。如果您尝试按原样运行代码,则它将失败,并显示语法错误。
push
行(标记为(2)
)是foreach
循环的一部分,但缩进时好像在外面。要么缩进更多(以与(1)
对齐),要么您需要在其前面添加}
。两种选择都没有太大意义:
push
在foreach
循环之外,则next
语句(以及整个foreach
循环)无效。可以删除它。push
在foreach
循环内,则每个目录条目($filelist
)将被多次推送,@not_included
中的每一行都会被推送一次(除了在@not_included
中某处列出的名称;这些名称将被减少一倍。)还有其他几个问题。例如:
$filelist =~ s/\.//g
从文件名中删除所有点,例如file_c.sv
到file_csv
中。这意味着它将永远不会与您的输入文件中的NOT_INCLUDED=file_c.sv
相匹配。next if s///
部分意味着循环会跳过名称中包含点的所有文件,例如Output1.sv
或Output2.sv
。Folder1Folder1Folder1Folder2Folder2Folder2file_afile_afile_bfile_b
中的OUTPUT.txt
。INFILE
和DIR
。这是我编写代码的方式:
#!/usr/intel/perl
use strict;
use warnings;
my $input_file = 'INPUT.txt';
my %is_blacklisted;
{
open my $fh, '<', $input_file or die "$0: $input_file: $!\n";
while (my $line = readline $fh) {
chomp $line;
if ($line =~ s!\ANOT_INCLUDED=!!) {
$is_blacklisted{$line} = 1;
}
}
}
my $path = 'experiment';
my @results;
{
opendir my $dh, $path or die "$0: $path: $!\n";
while (my $entry = readdir $dh) {
next
if $entry eq '.' || $entry eq '..'
|| $entry =~ /\.list\z/
|| $entry =~ /\.swp\z/
|| $is_blacklisted{$entry};
push @results, $entry;
}
}
@results = sort @results;
my $output_file = 'OUTPUT.txt';
{
open my $fh, '>', $output_file or die "$0: $output_file: $!\n";
for my $result (@results) {
print $fh "$result\n";
}
}
INPUT.txt
的内容(更具体地说,NOT_INCLUDED=
之后的部分)被读入哈希(%is_blacklisted
)中。这样可以轻松查找条目。
然后,我们处理目录条目。我们跳过.
和..
(我假设您不想要这些)以及所有以*.list
或*.swp
结尾的文件(在您的原始代码中) 。我们还将跳过所有列入黑名单的文件,即在INPUT.txt
中被指定为排除的文件。其余条目收集在@results
中。
我们对结果进行排序,并将其写入OUTPUT.txt
,每行一个条目。
答案 1 :(得分:1)
这里没有过多偏离您的代码,这是解决方案。请找到评论:
#!/usr/intel/perl
use strict;
use warnings;
my $input_file = "INPUT.txt";
open ( OUTPUT, ">OUTPUT.txt" );
file_in_directory();
close OUTPUT;
sub file_in_directory {
my $path = "experiment/";
my @unsort_output;
my %not_included; # creating hash map insted of array for cleaner and faster implementaion.
open ( INFILE, "<", $input_file);
while (my $file = <INFILE>) {
if ($file =~ /NOT_INCLUDED/) {
$file =~ s/NOT_INCLUDED=//;
$not_included{$file}++; # create a quick hash map of (filename => 1, filename2 => 1)
}
}
close INFILE;
opendir ( DIR, $path ) || die "Error in opening dir $path\n";
while ( my $filelist = readdir (DIR) ) {
next if $filelist =~ /^\.\.?$/xms; # discard . and .. files
chomp $filelist;
next if ( $filelist =~ m/\.list$/ );
next if ( $filelist =~ m/\.swp$/ );
next if ( $filelist =~ s/\.//g);
if (defined $not_included{$filelist}) {
next;
}
else {
push @unsort_output, $filelist;
}
}
closedir(DIR); # earlier the closedir was inside of while loop. Which is wrong.
my @output = sort @unsort_output;
print OUTPUT join "\n", @output;
}