Справка по оператору тестирования файла Perl - PullRequest
4 голосов
/ 18 апреля 2010

Это действительно базовая проблема, но я новичок в Perl и не могу понять, в чем проблема. Я просто пытаюсь изолировать файлы в каталоге, но оператор -d продолжает обрабатывать все содержимое папки как файлы ...

@ content - это мой массив, и когда я запускаю это:

use strict;

if ($ARGV[1]) {
    die("Error: You can only monitor one directory at a time\n");
}

my $directory = $ARGV[0] || die "Error: No directory defined\n";

opendir(DIR, $directory) || die "Error: Can't open dir $directory: $!";
my @contents = readdir(DIR);

foreach my $item(@contents) {
    if (-d $item) { next; }
    print"$item is a file\n"; 
}

closedir (DIR);

Я продолжаю получать и папки, и файлы. В качестве альтернативы, если я использую -f, я ничего не получу.

edit: это вывод -

file01.txt is a file
folder 01  is a file
folder 02 is a file
Screen shot 2010-04-18 at 1.26.17 PM.png is a file

Я запускаю это на OSX

edit: dir ls -l output:

aaron ~/Documents/test: ls -l
total 112
-rw-r--r--@ 1 aaron  staff  51235 18 Apr 13:26 Screen shot 2010-04-18 at 1.26.17 PM.png
-rw-r--r--@ 1 aaron  staff      7 18 Apr 13:26 file01.txt
drwxr-xr-x  3 aaron  staff    102 18 Apr 13:25 folder 01
drwxr-xr-x  2 aaron  staff     68 18 Apr 13:25 folder 02

Ответы [ 3 ]

5 голосов
/ 18 апреля 2010

Решение

Я тестировал с '.' в качестве каталога ... вы тестируете с другим каталогом. Имена, прочитанные из каталога, затем проверяются относительно текущего каталога. Если я использую другое имя каталога, я получу почти все, кроме '.' и «..» указаны как файлы независимо от того.

Если вы добавите имя к значению $ ARGV [0], вы получите ожидаемый результат:

#!/bin/perl -w

use strict;

if ($ARGV[1]) {
    die("Error: You can only monitor one directory at a time\n");
}

my $directory = $ARGV[0] || die "Error: No directory defined\n";

opendir(DIR, $directory) || die "Error: Can't open dir $directory: $!";
my @contents = readdir(DIR);

foreach my $item(@contents) {
    next if -d "$ARGV[0]/$item";
    print "$ARGV[0]/$item is a file\n"; 
}

closedir (DIR);

Предыдущие попытки объяснить

Это работает на MacOS X:

#!/bin/perl -w
use strict;

my @contents = <*>;

foreach my $item (@contents)
{
    print "== $item\n";
    next if -d $item;
    print "$item is a file\n";
}

Тест:

MiniMac JL: perl -c xx.pl
xx.pl syntax OK
MiniMac JL: perl xx.pl
== cproto-4.7g
== fpqsort1
fpqsort1 is a file
== fpqsort1.h
fpqsort1.h is a file
== fpqsort2
fpqsort2 is a file
== fpqsort2.c
fpqsort2.c is a file
== gcc-predef.h
gcc-predef.h is a file
== git-1.6.5.7
== go
== makefile
makefile is a file
== qs-test1.c
qs-test1.c is a file
== qs-test2.c
qs-test2.c is a file
== RCS
== rep-report.txt
rep-report.txt is a file
== select.c
select.c is a file
== soq
== xx.pl
xx.pl is a file
MiniMac JL: 

С учетом незначительно модифицированной версии кода в вопросе:

#!/bin/perl -w

use strict;

if ($ARGV[1]) {
    die("Error: You can only monitor one directory at a time\n");
}

my $directory = $ARGV[0] || die "Error: No directory defined\n";

opendir(DIR, $directory) || die "Error: Can't open dir $directory: $!";
my @contents = readdir(DIR);

foreach my $item(@contents) {
    print "<<$item>>\n";
    next if -d $item;
    print"$item is a file\n"; 
}

closedir (DIR);

Запустив его в том же каталоге, что и раньше, я получаю вывод:

Minimac JL: perl yy.pl .
<<.>>
<<..>>
<<cproto-4.7g>>
<<fpqsort1>>
fpqsort1 is a file
<<fpqsort1.h>>
fpqsort1.h is a file
<<fpqsort2>>
fpqsort2 is a file
<<fpqsort2.c>>
fpqsort2.c is a file
<<gcc-predef.h>>
gcc-predef.h is a file
<<git-1.6.5.7>>
<<go>>
<<makefile>>
makefile is a file
<<qs-test1.c>>
qs-test1.c is a file
<<qs-test2.c>>
qs-test2.c is a file
<<RCS>>
<<rep-report.txt>>
rep-report.txt is a file
<<select.c>>
select.c is a file
<<soq>>
<<xx.pl>>
xx.pl is a file
<<yy.pl>>
yy.pl is a file
Minimac JL:

Обратите внимание на идиому Perlish 'next if -d $item;'. Также обратите внимание на методы отладки: печатайте имена по мере их прохождения через массив - использование «<<» и «>>» для окружения имени помогает выявить странные побочные эффекты (такие как перевод строк в именах). Я дважды проверил, что приведенный код дает тот же результат - да. И я работаю на MacOS X 10.6.3 со стандартным Perl.

3 голосов
/ 18 апреля 2010

Из Perldoc на readdir :

Если вы планируете проверить возвращаемые значения из readdir, вам лучше добавить нужный каталог.В противном случае, поскольку мы не выполнили команду chdir, он бы протестировал не тот файл.

Отладочный код:

#!/usr/bin/perl
use strict;

if ($ARGV[1]) {
    die("Error: You can only monitor one directory at a time\n");
}

my $directory = $ARGV[0] || die "Error: No directory defined\n";

opendir(DIR, $directory) || die "Error: Can't open dir $directory: $!";
my @contents = readdir(DIR);

foreach my $item (@contents) {
    print "\$item=$item\n";
    print "$item is a file \n" if (-f $directory."/".$item); 
    print"$item is a dir\n" if (-d $directory."/".$item);  
}

closedir (DIR);
2 голосов
/ 18 апреля 2010

Я думаю, у вашего @contents есть новые строки в конце файла. Попробуйте добавить chomp:

foreach $item(@contents) {
  chomp($item);
  next if (-d $item); 
  print"$item is a file\n";       
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...