为什么我的if(-f)不能正常工作?

时间:2014-10-11 20:24:34

标签: perl foreach systems-programming

当最初检查ARGV [0]是否是文件或目录时,它可以正常工作并获得准确的结果。然后再进入子文件我再次尝试它并没有返回任何东西。这可能看起来像一个小傻问题,但我是学生,并在周末帮助编程很少。有时一双新的眼睛可以提供帮助。谢谢你。

#!/usr/bin/perl -w

my %hash;
my $args = @ARGV;

my $dh = $ARGV[0];

if ( -f $dh ) {
    words($dh);

} elsif ( -d $dh ) {
    files($dh);
}

sub words {
    open( my $file, '<', $_[0] ) or die 'cant open file';
    while ( my $line = <$file> ) {
        chomp $line;
        @words = split( /\s+/, $line );
        foreach $word (@words) {
            $word =~ tr/A-Z/a-z/;
            $hash{$word}++;
        }
    }

    foreach $key ( keys %hash ) {
        print $key. " " . $hash{$key} . "\n";
    }
}

sub files {
    opendir( DH, $_[0] );
    my @paths = grep !/^\./, readdir(DH);
    closedir(DH);
    foreach (@paths) {
        if ( -f $_ ) {
            print $_. "\n";
        }
    }
}

2 个答案:

答案 0 :(得分:3)

您错过了文件的路径

if (-f "$_[0]/$_") ..

或使其不那么模糊,

sub files{
  my ($path) = @_;

  opendir(my $DH, $path);
  my @paths = grep !/^\./, readdir($DH);
  closedir($DH);

  foreach (@paths) {
    if (-f "$path/$_") {
       print "$_\n";
    }
  }
}

答案 1 :(得分:1)

如前所述,readdir的返回值仅包含基本名称。因此,要进行文件测试,您必须chdir或明确包含路径信息。

if (-f "$_[0]/$_") {

一种替代解决方案是使用Path::Class或类似的模块来执行跨平台路径规范操作。

以下是使用此模块重写的脚本:

use strict;
use warnings;

use Path::Class;

my $path = shift // die "Usage: $0 <Dir or File>\n";

words($path) if -f $path;
files($path) if -d $path;

sub words {
    my $file = file(shift);

    my %count;
    $count{ lc($_) }++ for split ' ', $file->slurp;

    for my $key ( keys %count ) {
        printf "%s %s\n", $key, $count{$key};
    }
}

sub files {
    my $dir = dir(shift);

    for ( $dir->children ) {
        next if $_->is_dir;
        print "$_\n", $_->basename;
    }
}