【问题标题】:Perl: Finding a File in Directory and Assigning it to a VariablePerl:在目录中查找文件并将其分配给变量
【发布时间】:2012-08-04 12:58:53
【问题描述】:

我正在尝试开发一个 perl 脚本,它可以在用户的​​ 所有 目录中查找特定文件名,而无需用户指定文件的完整路径名。

例如,假设感兴趣的文件是focus.qseq。它位于/home/path/directory/。在命令行中,通常用户必须指定文件的路径名才能访问它,例如:/home/path/directory/focus.qseq

我希望用户只需在命令行中输入sample.qseq,然后perl 脚本就会自动将正确的文件分配给一个变量。如果文件是重复的但在不同的目录中,那么终端将显示这些文件的完整路径名,用户可以更好地指定他们想要的文件。

我阅读了有关 File::Find 模块的信息,但它并没有达到我想要的效果。

这是我实现上述代码的最佳尝试:

#!/usr/bin/perl
use strict; use warnings;
use File::Find;

my $file = shift;

# I want to search from the top down (you know, recursively) so first I look in the home directory
# I believe $ENV{HOME} is the same as $~/home/user
find(\&wanted, @$ENV{HOME}); 
open (FILEIN, $file) or die "couldn't open $file for read: $!\n";

我真的不明白wanted 子例程在这个模块中是如何工作的。如果有人知道实现我上面描述的代码的另一种方法,请随时提出建议。谢谢你

编辑: 如果我想使用命令行选项怎么办。像这样:

#!/usr/bin/perl
use strict; use warnings;
use File::Find;
use Getopt::Long qw(GetOptions);

my $file = '';
GetOptions('filename|f=s' => \$file);

# I believe $ENV{HOME} is the same as $~/home/user
find(\&wanted, @$ENV{HOME});
open (FILEIN, $file) or die "couldn't open $file for read: $!\n";

如何实现这个?

【问题讨论】:

    标签: perl file directory user-input


    【解决方案1】:

    File::Find 应该没问题。

    你可以像这样循环遍历所有内容

    find( sub {
        say $File::Find::name if ($_ eq $userInput);
    }, '/');
    

    那应该做你想做的事。不要忘记chomp用户输入,除非它是通过@ARGV传递的

    '/' 更改为您要搜索的任何目录,或者您也可以让用户指定。

    【讨论】:

    • 如果我想使用命令行选项怎么办?所以在命令行我会输入perl script01.pl --filename focus.qseq你能解释一下上面的代码是否会改变吗?
    • 如果你想在你的 perl 脚本中使用命令行选项,你应该使用Getopt::Long 模块;它的记录很好。如果您想将它们传递给 shell,您可以拨打 system() 电话或使用反引号
    【解决方案2】:

    一个问题是您尝试在未指定路径的情况下打开文件。您需要创建另一个变量,例如$path。现在,您可以将\&wanted 作为对您在别处编写的子例程的引用传递,但您可能不得不求助于全局变量。使用闭包会更好。

    您的代码可能如下所示:

    #!/usr/bin/perl
    use strict; use warnings;
    use File::Find;
    use Getopt::Long qw(GetOptions);
    
    my ($file, $path);
    GetOptions('filename|f=s' => \$file);
    
    # Set $path when file is found.
    my $wanted = sub { $path = $File::Find::name if ($_ eq $file); };
    
    find($wanted, $ENV{HOME});
    if (!$path) {
        # complain
    }
    open (FILEIN, $path) or die "couldn't open $file for read: $!\n";
    

    【讨论】:

    • 我在my $wanted = sub { $path = $Find::File::name if ($_ eq $file); }; 行遇到错误。终端给我以下错误Name "Find::File::name" used only once: possible typo at wrapper_example.pl line 17.invalid top directory at /usr/share/perl/5.14/File/Find.pm line 464.你知道invalid top directory是什么意思吗?
    • 抱歉,我写的是Find::File 而不是File::Find。我在回答中更正了它。
    • 我原本是File::Find,但我遇到了同样的错误,所以我更改了find($wanted, @$ENV{HOME}.'/');,因为我认为/home/user/$ENV{HOME}/ 相同。现在我收到权限错误。上面写着Can't cd to (/var/spool/postfix/) active: Permission denied at wrapper_example.pl line 19
    • 对。另一个编辑。 @$ENV{HOME} 不正确,导致未定义的变量,因此您的脚本改为查看根目录。 (在 Perl 中,印记 (@, $, &) 在哈希查找之前进行评估,因此它认为 $ENV 是对数组的引用,但事实并非如此。如果你想在几个目录,只需在 find() 例程中以逗号分隔的列表形式列出它们。)
    • 我们在子例程中设置$path 的方式有问题。我在if (!$path) 循环中放置了一个打印语句ERROR!!!。终端正在返回该错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 2018-07-24
    • 1970-01-01
    • 2014-06-02
    相关资源
    最近更新 更多