1

我正在尝试解析位于一个目录的子目录中的特定 XML 文件。出于某种原因,我收到错误消息说文件不存在。如果该文件不存在,它应该移动到下一个子目录。

这是我的代码

        use strict;
        use warnings;
        use Data::Dumper;
        use XML::Simple;

        my @xmlsearch = map { chomp; $_ } `ls`;

        foreach my $directory (@xmlsearch) {
            print "$directory \n";
            chdir($directory) or die "Couldn't change to [$directory]: $!";
            my  @findResults = `find   -name education.xml`;

         foreach my $educationresults (@findResults){
            print $educationresults;
            my $parser = new XML::Simple;
            my $data = $parser->XMLin($educationresults);
            print Dumper($data);
            chdir('..');         
         }

        }

      ERROR
      music/gitar/education.xml
      File does not exist: ./music/gitar/education.xml
4

2 回答 2

1

使用chdir您所做的方式会使代码 IMO 的可读性降低。您可以为此使用File::Find

use autodie;
use File::Find;
use XML::Simple;
use Data::Dumper;

sub findxml {
    my @found;

    opendir(DIR, '.');
    my @where = grep { -d && m#^[^.]+$# } readdir(DIR);
    closedir(DIR);

    File::Find::find({wanted => sub {
        push @found, $File::Find::name if m#^education\.xml$#s && -f _;
    } }, @where);
    return @found;
}

foreach my $xml (findxml()){
    say $xml;
    print Dumper XMLin($xml);
}
于 2012-06-08T15:43:32.350 回答
0

每当您发现自己依赖反引号来执行 shell 命令时,您应该考虑是否有适当的 perl 方法来执行此操作。在这种情况下,有。

ls可以替换为<*>,这是一个简单的 glob。该行:

my @array = map { chomp; $_ } `ls`;

只是一种迂回的说法

chomp(my @array = `ls`);  #  chomp takes list arguments as well

但当然正确的方法是

my @array = <*>;  # no chomp required

现在,所有这一切的简单解决方案就是做

for my $xml (<*/education.xml>) { # find the xml files in dir 1 level up

这将覆盖一级目录,没有递归。对于完全递归,使用File::Find

use strict;
use warnings;
use File::Find;

my @list;
find( sub { push @list, $File::Find::name if /^education\.xml$/i; }, ".");

for (@list) {
    # do stuff
    # @list contains full path names of education.xml files found in subdirs
    # e.g. ./music/gitar/education.xml
}

您应该注意,不需要更改目录,根据我的经验,不值得麻烦。而不是这样做:

chdir($somedir);
my $data = XMLin($somefile);
chdir("..");

只需这样做:

my $data = XMLin("$somedir/$somefile");
于 2012-06-08T15:42:31.947 回答