0

我有一个目录,其中包含约 5000 个 2,400 大小的 .txt 文件。

我只想要该目录中的一个文件名;顺序无所谓。

该文件将被处理和删除。

这不是脚本工作目录。

意图是:

  • 打开该文件,
  • 阅读,
  • 做一些事情,
  • 取消链接然后
  • 循环到下一个文件。

我的粗略尝试不仅仅检查 .txt 文件,而且还必须仅针对一个文件名获取所有 ~5000 个文件名。我也可能调用了太多模块?

Verify_Empty子旨在验证是否有一个目录并且其中有文件,但是我的尝试失败了,所以我在这里寻求帮助。

#!/usr/bin/perl -w
use strict;
use warnings;
use CGI;
use CGI ':standard';
print CGI::header();
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
###
use vars qw(@Files $TheFile $PathToFile);
my $ListFolder = CGI::param('openthisfolder');
Get_File($ListFolder);
###
sub Get_File{
  $ListFolder = shift;
  unless (Verify_Empty($ListFolder)) {
    opendir(DIR,$ListFolder);
    @Files = grep { $_ ne '.' && $_ ne '..' } readdir(DIR);
    closedir(DIR);
    foreach(@Files){
      $TheFile = $_;
    }
    #### This is where I go off to process and unlink file (sub not here) ####
    $PathToFile = $ListFolder.'/'.$TheFile;
    OpenFileReadPrepare($PathToFile); 
    #### After unlinked, the OpenFileReadPrepare sub loops back to this script. 
  }
  else {
    print qq~No more files to process~;
    exit;
  }
  exit;
}
    ####
sub Verify_Empty {
  $ListFolder = shift;
  opendir(DIR, $ListFolder) or die "Not a directory";
  return scalar(grep { $_ ne "." && $_ ne ".." } readdir(DIR)) == 0;
  closedir(DIR);
}

显然我对此很陌生。这种方法看起来很“饿”?抓取一个文件名并处理它似乎很多!指导会很棒!

编辑 - 最新尝试

my $dir = '..';
my @files = glob "$dir/*.txt";
for (0..$#files){
$files[$_] =~ s/\.txt$//;
}
my $PathAndFile =$files[0].'.txt';
print qq~$PathAndFile~;

这“有效”但是,它仍然获取所有文件名。到目前为止,这里没有一个例子对我有用。我想我今天会忍受这个,直到我弄明白为止。也许我会重新审视,看看是否有人提出了更好的办法。

4

3 回答 3

4

您可以在 while 循环中使用 readdir 循环。这样,readdir 不会返回所有文件,而是一次只提供一个文件,

# opendir(DIR, ...);
my $first_file = "";
while (my $file = readdir(DIR)) {

  next if $file eq "." or $file eq "..";
  $first_file = $file;
  last;
}
print "$first_file\n"; # first file in directory
于 2013-05-08T15:09:08.430 回答
4

readdir在列表上下文中调用,它返回所有目录条目。改为在标量上下文中调用它:

my $file;
while( my $entry = readdir DIR ) {

    $file = $entry, last if $entry =~ /\.txt$/;        
}

if ( defined $file ) {
    print "found $file\n";
    # process....
}

此外,您阅读了两次目录;一次看它是否有任何条目,然后处理它。您真的不需要查看目录是否为空;您可以在处理循环期间免费获得它。

于 2013-05-08T16:49:06.620 回答
2

除非我大错特错,否则您想要的只是遍历目录中的文件,而所有关于“第一个或最后一个”和“顺序无关紧要”和删除文件的内容只是对如何执行此操作感到困惑。

因此,让我以一种非常简单的方式为您介绍它,看看它是否真的符合您的要求:

my $directory = "somedir";
for my $file (<$directory/*.txt>) {
    # do stuff with the files
}

glob将与 *nix shell 执行相同的操作,它将列出带有.txt扩展名的文件。如果您想对循环内的文件进行进一步测试,那很好。

缺点是在内存中保留了 5000 个文件名,而且如果处理此文件列表需要时间,它可能会与也访问这些文件的其他进程发生冲突。

另一种方法是在 while 循环中简单地读取文件readdir,例如他的回答中提到的 mpapec 。好处是每次读取新文件名时,文件都会在那里。此外,您不必在内存中保留大量文件。

于 2013-05-08T15:09:48.587 回答