0

下午好,stackoverflow 的朋友们!

我被分配了以下任务,并想了解如何查看文件或目录是否存在。

"提示用户输入一个参数(注意这个脚本只接受一个参数,如果用户输入包含零个或多个参数,应该报告警告/错误),检查输入参数是文件名还是目录名。

1) 如果用户输入的是文件,当文件为空文件时退出,并打印文件的最后一行。

2)如果用户输入的是目录,则目录为空时退出,使用哈希表记录该目录内的文件名和这些文件的评估年龄(自上次评估文件以来的天数),找到目录中最旧的文件(基于修改时间),并打印该文件的绝对路径。”

在过去的 2 天里,我一直在寻找有关如何使用 File::Find 但不能使用的详细说明。下面是我的代码,我想用 File::Find 替换 -e $input 部分,因为使用 -e 文件运算符,我只能在当前目录中搜索,而不能在整个系统中搜索。我期待您的回复,并非常感谢您的宝贵时间。

#! /usr/bin/perl
# Assignment 9, check and read files and directories

use strict;
use warnings;
use Module1;

assnintro();

my @parameter;
my $input;

do {          # This loop keeps calling pamcheck subroutine until the 1 param entered
              # is a file in the directory, but I'd to expand the file test operator
              # to all directories
    $input     = ();
    @parameter = ();
    pamcheck( \@parameter );
    $input = $parameter[0];

    if ( -e $input ) { }    # Instead of simply checking current directory, I want to 
                            # I want to see that the file exists in my system
    else {
        print color 'red';
        print "The file or directory you entered, doesn't exist.\n";
        print color 'reset';
    }
} until ( -e $input );     

if ( -d $input ) {
    print "I am a directory.\n";
} else {
}

exit;

sub pamcheck {   # This subroutine asks user to to enter a file or directory name
    my ($parameter) = @_;     # In the terminal, "parameters" are separated by space
    my $elementcount;     # Do elem ct. to make sure usr only entered 1 parameter
    do {
        @$parameter = ();
        print "Enter one file or directory name: ";
        @_ = split( /\s+/, <> );     # "Enter" key act as Ctrl D to avoid infinite 
                                     # param entry
        push( @$parameter, @_ );
        $elementcount = 0;

        foreach (@_) {
            $elementcount++;
        }

        if ( $elementcount != 1 ) {      # Error msg if 1 param isn't entered
            print color 'red';
            print "Please enter only ONE parameter.\n";
            print color 'reset';
        } else {
        }
    } until ( $elementcount eq 1 );  # Loop continues until one param is entered
}
4

1 回答 1

1

File::Find不做你认为它做的事。它基于find遍历目录树的 Unix 命令。(并且可能对目录树中的所有文件进行处理)。

你需要这个的原因是,在一个有符号链接、挂载点等的世界中,深度遍历文件系统比你想象的要难。因此,一个实用程序可以做到这一点。

让你File::Find做的是指定一段代码在每个文件上运行,例如 if find.

举个例子 -

sub do_something {
   print $File::Find::name,"\n";
}

find ( \&do_something, "." );  

除此之外 - 你的代码中有几件事似乎表明你正在朝着一个奇怪的方向前进。

  • 通过在标量上下文中测试数组,计算数组中的元素要简单得多。代替:

    for (@array){$elementcount++; }

你可以这样做:

my $elementcount = @array; 
  • 分割STDIN空格有点冒险,因为它假设你没有包含空格的文件名。但现在让我们坚持下去。

  • 永远不要给@_. 这是一个内置变量,弄乱它会以奇怪和可怕的方式破坏事物。

  • 为什么将“获取输入”封装到子程序中?

无论如何-假设您需要遍历文件系统以找到您的目录/文件:

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

sub find_matches {
    my ( $search, $results_ref ) = @_;
    if ( $_ eq $search ) {
        push( @$results_ref, $File::Find::name );
    }
}

while (<STDIN>) {
    print "Please enter directory or file name:\n";
    my @parameters = split(/\s+/); #split input in one or more whitespace.

    #won't work if filename includes whitespace!

    unless ( scalar @parameters == 1 ) {
        print "Please enter only one value\n";
        next;
    }
    my $search_text = pop @parameters;
    my @results;
    find( sub { \&find_matches( $search_text, \@results ) },
        "/path/to/search" );

    #now results has a list of all full paths to your files.
    #because you traversed, you may well have  duplicates.

    if ( not @results ) {
        print "No matches found\n";
    }
    foreach my $full_file_path (@results) {
        if ( -d $full_file_path ) {
            print "$full_file_path is a directory\n";

            # do directory stuff;
            last;
        }
        if ( -z $full_file_path ) {
            print "$full_file_path is zero length\n";

        }
    }
    last; #breaks you out the while loop - the 'next' above will skip this line
          #if you don't have a valid parameter. 
}

希望这应该让你开始?正在发生的事情是 - 您正在使用 File::Find 为您提供文本字符串的匹配列表,然后您可以单独浏览和处理。请记住,如果您有一个匹配的目录文件,您的分配规范不清楚您应该做什么,这就是为什么我不相信您需要进行遍历。

于 2014-11-03T14:24:31.593 回答