开发者

How can I create an array of directory contents in Perl?

I need to make 3 arrays from the contents of $directory. The first one I can use:

$var = qx{ls $directory};
print $var;

However the second and third I want to grep for "Primary *" and "Secondary *"

I've used the commands:

my @primary = 0;
my @secondary = 0;

@primary = system("ls test_77 > test | grep Primary* test");
print @primary;
@secondary = system("ls test_77 > test | grep Secondary* test");
print @secondary;

BUT, it includes a zero on the output:

PrimaryCPE_Option_A.txt.test_77
PrimaryCPE_Option_B.txt.test_77
0SecondaryCPE_Option_A.txt.test_77
SecondaryCPE_Option_B.txt.test_77
0

What can it be? At first it looks like it might be th开发者_C百科e original zero, but I can change the initial value of either and it doesn't work.


Perl can do this without calling system commands.

@secondary=glob("*Secondary*.txt");
print @secondary;
@primary=glob("*Primary*.txt")
print @primary;

Other ways are using opendir()/readdir(), or while loop eg

while(my $file=<*Primary*txt>){
  push(@secondary,$file);
}

Or

push (@secondary,$_) while<*Secondary*.txt> ;


The following will read all the files in the current directory, and store them into one array. It excludes sub-directories, but it does include files which start with the . character. Then, it creates the 2 other arrays from the 1st array. Refer to File::Slurp.

use strict;
use warnings;
use File::Slurp qw(read_dir);

my @all_files = grep { -f $_ } read_dir('./');
my @pfiles = grep {/^Primary/  } @all_files;
my @sfiles = grep {/^Secondary/} @all_files;

I'll try to address your questions now. system returns the exit status of the external command (ls, for example). It does not return the directory listing. You would use qx to return the directory listing. Refer to system.

So, since your ls command succeeds, its exit status is 0. Thus, system returns 0. This value is stored into the 1st element of your array. That is the only value in your array. Any other output you see is coming from your grep, I believe.

Also, the only way I come close to reproducing your output is to change the pipe to a semicolon in your system call, and by getting rid of *:

@primary = system("ls test_77 > test ; grep Primary test");


This is how I would write this program:

#! /usr/bin/env perl
use strict;
use warnings;
use autodie;  # this is so that you don't have to check opendir(), and readdir().

my @files = grep {
  -f $_;
} do{
  opendir my $dir, '.';
  readdir $dir;
};

my @primary   = grep {/Primary/  } @files;
my @secondary = grep {/Secondary/} @files;

You are putting the 0 on the list by declaring the arrays like this:

my @primary = 0;

If you want an empty array, you just declare it.

my @primary;

If you want to explicitly set an array to nothing:

@primary = ();


I think you should be using opendir (and readdir, etc.).

At the moment you're spawning off new processes and piping them together, whereas Perl can do all of this in process using standard built-in commands. The results will come back immediately as an array for further processing using Perl regular expressions.

(Note that you need to escape the * in your grep if you continue with your approach.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜