我想捕获CWD
中的文件和@files
:中的文件之间的差异
#!/usr/bin/perl -w
use Cwd qw[getcwd abs_path];
opendir CWD, getcwd;
@files=grep{!/^./}readdir CWD;
push @files, ("foo.txt", "bar.txt");
for my $i (@files){
@difference=grep { !/^./ and $i!=$_ } readdir CWD;
}
print "$_n" for @differenc
现在curect目录有以下文件:
$ls
a.txt e.txt getopt.html
用这个表达式push @files, ("foo.txt", "bar.txt");
数组有以下元素:("foo.txt", "bar.txt", "a.txt", "e.txt", "getopt.html")
,这是正确的,但现在我只想选择那些在CWD中是而不是的文件:@difference=grep { !/^./ and $i!=$_ } readdir CWD;
,所以我希望数组@difference
再次只有("foo.txt", "bar.txt")
(我现在这没有意义,只是举个例子(。但是打印没有输出任何内容,这是怎么回事?
您的代码有很多问题:
-
您的第二个
readdir
(在for my $i (@files)
循环中(没有读取任何内容,因为第一个(@files=grep{!/^./}readdir CWD;
(已经读取了整个目录。您可以先使用rewinddir
,但简单地使用@files
的副本(在推送foo.txt
和bar.txt
之前(会更简单、更高效。 -
您正在使用
!=
而不是ne
来比较字符串。 -
循环的每次迭代都会擦除
@differences
的上一个值,因为您使用=
对其进行了赋值。大概push
会更有意义。 -
循环中的逻辑有点缺陷。
grep
返回满足条件的元素,但您更感兴趣的是是否有任何元素满足条件 -
您应该检查
opendir
是否成功(通过在opendir
行中添加or die ...
(。此外,请注意,open my $CWD, getcwd
等效于更简单的open my $CWD, "."
。
你可能想做的是:
use strict;
use warnings;
opendir my $CWD, "." or die "Could not open '.': $!";
my @files = grep{!/^./} readdir $CWD;
my @init_files = @files;
push @files, ("foo.txt", "bar.txt");
my @difference;
for my $i (@files){
push @difference, (grep { !/^./ and $i eq $_ } @init_files) ? () : $i;
}
print "$_n" for @difference
然而,这远不是有效的,而且它需要更复杂。我建议:
my %files = map { $_ => 1 } grep {!/^./} readdir $CWD;
my @difference;
for ("foo.txt", "bar.txt") {
push @difference, $_ if ! exists $files{$_};
}
print "$_n" for @difference
请注意,我已将use strict; use warnings;
添加到脚本中。始终将它们添加到代码中。虽然在这种特定的情况下,它不会帮助你找出问题所在,但它会在未来为你节省无数的时间。此外,始终使用词法文件/目录句柄(即,使用opendir my $CWD, "dir"
而不是open CWD, "dir"
(。
在同一个文件句柄上有两个readdir
操作。一旦第一个到达EOF,就没有什么可返回的了。
在第二次迭代之前添加`rewinddir操作。