【问题标题】:Perl program help on opendir and readdir关于 opendir 和 readdir 的 Perl 程序帮助
【发布时间】:2011-05-15 23:06:42
【问题描述】:

所以我有一个程序要清理一些文本文件。该程序要求用户输入包含这些文本文件的目录的完整路径。从那里我想读取目录中的文件,将它们打印到一个新文件(由用户指定),然后以我需要的方式清理它们。我已经编写了脚本来清理文本文件。

我向用户询问要使用的目录:

chomp ($user_supplied_directory = <STDIN>); 
opendir (DIR, $user_supplied_directory);

然后我需要读取目录。

my @dir = readdir DIR;

foreach (@dir) {

现在我迷路了。

有什么帮助吗?

【问题讨论】:

  • 用户如何指定新文件(特别是考虑到会有多个新文件)

标签: perl readdir opendir


【解决方案1】:

我不确定你想要什么。所以,我做了一些假设:

  • 当你说清理文本文件时,你的意思是删除文本文件
  • 您要写入的文件的名称由模式组成。

所以,如果我是对的,试试这样的:

chomp ($user_supplied_directory = <STDIN>);

opendir (DIR, $user_supplied_directory);
my @dir = readdir DIR;

foreach (@dir) {
    next if (($_ eq '.') || ($_ eq '..'));

    # Reads the content of the original file
    open FILE, $_;
    $contents = <FILE>;
    close FILE;

    # Here you supply the new filename
    $new_filename = $_ . ".new";

    # Writes the content to the new file
    open FILE, '>'.$new_filename;
    print FILE $content;
    close FILE;

    # Deletes the old file
    unlink $_;
}

【讨论】:

  • 你应该检查你的opendiropen调用的结果,否则use autodie;
【解决方案2】:

我建议您切换到 File::Find。一开始可能有点挑战,但它功能强大且跨平台。

但是,要回答您的问题,请尝试以下方法:

my @files = readdir DIR;
foreach $file (@files) {
   foo($user_supplied_directory/$file);
}

其中“foo”是您需要对文件执行的任何操作。一些注释可能会有所帮助:

  • 使用“@dir”作为文件数组有点误导
  • 文件夹名称需要添加到文件名前以获得正确的文件
  • 使用grep 丢弃不需要的文件和子文件夹可能很方便,尤其是“..”

【讨论】:

  • 文件::查找?问题中没有任何内容让我认为应该搜索嵌套目录。
  • 使用 “跨平台” 来表示 “甚至可以在 Microsoft 上工作” 是一种黄鼠狼式的委婉说法,有点政治正确性发疯的味道。
  • @tchrist 我喜欢跨平台工作的代码,而无需我付出太多额外的努力。这只是方便,不政治正确。在这种情况下,我无法判断正在使用哪个操作系统……坦率地说,我并不在意。
  • @ysth 我一般喜欢使用 File::Find,但这里可能太麻烦了。特别是如果它不熟悉。
【解决方案3】:

我今天写了一些使用readdir 的东西。也许你可以从中学到一些东西。这只是一个(有点)更大的程序的一部分:

our @Perls = ();

{
    my $perl_rx = qr { ^ perl [\d.] + $ }x;
    for my $dir (split(/:/, $ENV{PATH})) {
        ### scanning: $dir
        my $relative = ($dir =~ m{^/});
        my $dirpath = $relative ? $dir : "$cwd/$dir";
        unless (chdir($dirpath)) {
            warn "can't cd to $dirpath: $!\n";
            next;
        }
        opendir(my $dot, ".") || next;
        while ($_ = readdir($dot)) {
            next unless /$perl_rx/o;
            ### considering: $_
            next unless -f;
            next unless -x _;
            ### saving: $_
            push @Perls, "$dir/$_";
        }
    }
}

{
    my $two_dots = qr{ [.] .* [.] }x;
    if (grep /$two_dots/, @Perls) {
        @Perls = grep /$two_dots/, @Perls;
    }
}

{
    my (%seen, $dev, $ino);
    @Perls = grep {
        ($dev, $ino) = stat $_;
        ! $seen{$dev, $ino}++;
    } @Perls;
}

关键是push(@Perls, "$dir/$_")readdir 读取的文件名只是基本名称;它们不是完整的路径名。

【讨论】:

  • 感谢大家的回复。我认为通过这些帖子我可以完成工作。澄清我想做什么。我是一名生物学博士生,我使用 Fasta 文件。它们的格式非常简单,但是当您从 Internet 复制和粘贴文件时,您会得到比您想要的更多的换行符。我编写了一个脚本,它将打开一个文件,删除多余的空格和换行符,然后将文件保存到用户提供的位置。
  • 我现在想在脚本中添加一个函数,以便它打开一个充满 fasta 文件的目录,打开所有 fasta 文件并将它们复制到一个文件中(在用户提供的位置) .然后进行清洁。谢谢
  • @user520742,您可能会发现glob("$dir/*")readdir 更易于使用。你try Googling for Perl and Fasta了吗?我注意到第一个链接是over on Perlmonks。看起来有一个 Bio::SeqIO::fasta 是 Bio Perl 的一部分。另一个提示:如果您编辑您的用户个人资料,您可以拥有真实姓名。
  • 感谢网站的链接。我做了谷歌,但作为我博士学位的一部分,我希望做一些生物信息学,所以我试图自己写所有这些东西。我有很多这方面的书,但我希望看到我的确切问题的解决方案能帮助我更好地理解 opendir/readdir/etc。也感谢您对我的名字提出的建议。
  • chomp( 我的 $directory = );开放目录(目录,“$目录”)|| die("哦,不!我无法打开目录;我只是没有权力!"); #读取目录中的文件名到数组 my @dir = readdir DIR; #将目录中每个文件的内容复制到新文件中。 foreach my $dir (@dir) { next if ( ( $dir eq '.' ) || ( $dir eq '..' ) );打开 Dir_Files, "$directory\$dir";打印 MERGED "$directory\$dir\n";关闭目录文件; } 关闭目录;
【解决方案4】:

您可以执行以下操作,允许用户提供自己的目录,或者,如果用户未指定目录,则默认为指定位置。

该示例显示了opendirreaddir 的使用,将目录中的所有文件存储在@files 数组中,并且仅将以'.txt' 结尾的文件存储在@keys 数组中。 while 循环确保文件的完整路径存储在数组中。

这假定您的“文本文件”以“.txt”后缀结尾。我希望这会有所帮助,因为我不太清楚“清理文件”是什么意思。

use feature ':5.24';
use File::Copy;

my $dir = shift || "/some/default/directory";

opendir(my $dh, $dir) || die "Can't open $dir: $!";

while ( readdir $dh ) {
    push( @files, "$dir/$_");
}

# store ".txt" files in new array
foreach $file ( @files ) {
    push( @keys, $file ) if $file =~ /(\S+\.txt\z)/g;
}

# Move files to new location, even if it's across different devices
for ( @keys ) {
    move $_, "/some/other/directory/"; || die "Couldn't move files: $!\n";
}

请参阅perldoc of File::Copy 了解更多信息。

【讨论】:

    猜你喜欢
    • 2015-06-06
    • 2015-06-22
    • 2016-06-21
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 2021-05-16
    • 1970-01-01
    相关资源
    最近更新 更多