如何在Perl中查找与提示输入匹配的文件而不使用-e和-d。。。文件::找到唯一的方法?

如何在Perl中查找与提示输入匹配的文件而不使用-e和-d。。。文件::找到唯一的方法?,perl,file-find,Perl,File Find,下午好,朋友们 我被分配了以下任务,希望学习如何查看文件或目录是否存在 提示用户键入一个参数(请注意,此脚本仅接受一个参数,如果用户输入包含零个或多个参数,则应报告警告/错误),检查输入参数是文件名还是目录名 1) 如果用户输入是文件,请在文件为空文件时退出,然后打印文件的最后一行 2) 如果用户输入的是目录,请在目录为空时退出,使用哈希表记录此目录中的文件名以及这些文件的评估期限(自上次评估文件以来的天数),在目录中查找最旧的文件(基于修改时间),并打印此文件的绝对路径。” 在过去的两天里,我

下午好,朋友们

我被分配了以下任务,希望学习如何查看文件或目录是否存在

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

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

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

在过去的两天里,我一直在寻找有关如何使用File::Find的详细说明,但无法找到它。下面是我的代码,我想用File::Find替换-e$input部分,因为使用-e File操作符,我只能在当前目录中搜索,而不能搜索整个系统。我期待着您的回复,非常感谢您抽出时间

#! /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
}
#/usr/bin/perl
#作业9,检查并读取文件和目录
严格使用;
使用警告;
使用模块1;
assnintro();
我的@参数;
我的$input;
do{#这个循环一直调用pamcheck子例程,直到输入1参数
#是目录中的一个文件,但我想展开file test操作符
#到所有目录
$input=();
@参数=();
pamcheck(\@参数);
$input=$parameter[0];
如果(-e$input){}#而不是简单地检查当前目录,我想
#我想查看该文件是否存在于我的系统中
否则{
打印颜色为“红色”;
打印“您输入的文件或目录不存在。\n”;
打印颜色“重置”;
}
}直至(-e$投入);
如果(-d$输入){
打印“我是一个目录。\n”;
}否则{
}
出口
sub pamcheck{#此子例程要求用户输入文件或目录名
my($parameter)=@#在终端中,“parameters”用空格分隔
my$elementcount;#Do elem ct.以确保usr只输入了1个参数
做{
@$parameter=();
打印“输入一个文件或目录名:”;
@_=split(/\s+/,);#“Enter”键作为Ctrl-D键,以避免出现无限大
#参数输入
推送(@$parameter,@u3;);
$elementcount=0;
foreach(foreach){
$elementcount++;
}
如果($elementcount!=1){#如果未输入1个参数,则返回错误消息
打印颜色为“红色”;
打印“请只输入一个参数。\n”;
打印颜色“重置”;
}否则{
}
}直到($elementcount eq 1)#循环继续,直到输入一个参数
}

文件::Find
不会做您认为它会做的事情。它基于Unix
find
命令,该命令遍历目录树。(并且可以对目录树中的所有文件执行某些操作)

您需要这样做的原因是,在一个有符号链接、挂载点等的世界中,深入遍历文件系统比您想象的要困难得多。因此,这是一个实用程序

File::Find
将允许您指定要在其上运行的代码块,例如,如果
Find
,则指定每个文件

例如—

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

find ( \&do_something, "." );  
撇开这一点不谈——代码中有几点似乎表明您正朝着一个奇怪的方向前进

  • 通过在标量上下文中测试数组,对数组中的元素进行计数要简单得多。 而不是:

    对于(@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;
子查找匹配{
我的($search,$results\u ref)=@;
如果($\uEQ$搜索){
推送(@$results\u ref,$File::Find::name);
}
}
而(){
打印“请输入目录或文件名:\n”;
my@parameters=split(/\s+/)#将输入拆分为一个或多个空格。
#如果文件名包含空格,则不起作用!
除非(标量@参数==1){
打印“请只输入一个值\n”;
下一个
}
我的$search\u text=pop@参数;
我的@results;
查找(sub{\&find\u匹配($search\u text,\@results)},
“/path/to/search”);
#现在,results有一个指向文件的所有完整路径的列表。
#因为您已遍历,所以很可能有重复项。
如果(不是@results){
打印“未找到匹配项\n”;
}
foreach my$full_file_路径(@results){
如果(-d$full\u文件\u路径){
打印“$full_file_path是一个目录\n”;
#做目录工作;
最后;
}
如果(-z$full_文件_路径){
打印“$full\文件\路径长度为零\n”;
}
}
最后;#中断while循环-上面的“next”将跳过这一行
#如果没有有效的参数。
}
希望这能让你开始吗?所发生的事情是-您正在使用File::Find为文本字符串提供一个匹配列表,然后您可以逐一查看和处理该列表。请记住,如果你有直接的任务,你的任务规范不清楚你应该做什么