【问题标题】:finding a file in directory using perl script使用 perl 脚本在目录中查找文件
【发布时间】:2021-06-14 06:47:39
【问题描述】:

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

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

cd /home/path/directory/project/userabc/data.list

相反,我希望用户只需在命令行中输入 script.pl ABC,然后 Perl 脚本将自动运行并检索 data.list. 中的信息,在我的情况下,计算行数和使用 curl 上传。剩下的就完成了,就是可以自动定位文件的部分了

【问题讨论】:

  • "我从这个开始,但它无法正常工作,因为它只能在其当前目录中找到文件:" - 我什至看不到你的脚本是如何做到这一点的。它只是打印出文件名。没有尝试将文件名与某个参数进行比较。这让我想知道您的实际问题是什么:从命令行获取文件名作为参数,将给定的文件名与findfiles 中的文件名进行比较,然后返回结果......?请把你实际遇到的问题描述的更清楚。
  • 该代码只是可以搜索文件名的东西,与问题不太相关,但我认为该代码将帮助我开始
  • 我不明白这个问题(ABC 是文件名吗?),但这似乎是File::Find 的直接工作。 Like:use File::Find; find(sub { if ($_ eq $filename) { say $File::Find::name } }, $dir);(其中$filename 是查找文件的名称)。查看链接文档

标签: linux perl


【解决方案1】:

尽管在 Perl 中非常可行,但这在 Bash 中看起来更合适:

#!/bin/bash

filename=$(find ~ -name "$1" )
wc -l "$filename"
curl .......

主要问题当然是如果您有多个文件data1,例如/home/user/dir1/data1/home/user/dir2/data1。您将需要一种方法来处理它。而你如何处理它取决于你的具体情况。

在 Perl 中会复杂得多:

#! /usr/bin/perl -w
    eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
        if 0; #$running_under_some_shell

use strict;

# Import the module File::Find, which will do all the real work
use File::Find ();

# Set the variable $File::Find::dont_use_nlink if you're using AFS,
# since AFS cheats.

# for the convenience of &wanted calls, including -eval statements:
# Here, we "import" specific variables from the File::Find module
# The purpose is to be able to just type '$name' instead of the
# complete '$File::Find::name'.
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

# We declare the sub here; the content of the sub will be created later.
sub wanted;

#  This is a simple way to get the first argument. There is no 
# checking on validity.
our $filename=$ARGV[0];


# Traverse desired filesystem. /home is the top-directory where we
# start our seach. The sub wanted will be executed for every file 
# we find
File::Find::find({wanted => \&wanted}, '/home');
exit;


sub wanted {
    # Check if the file is our desired filename
    if ( /^$filename\z/) {
        # Open the file, read it and count its lines
        my $lines=0;
        open(my $F,'<',$name) or die "Cannot open $name";
        while (<$F>){ $lines++; }
        print("$name: $lines\n");

        # Your curl command here
    }
}

您需要查看参数解析,我只是使用了$ARGV[0],但我不知道您的 curl 是什么样的。

一种更简单(虽然不推荐)的方法是滥用 Perl 作为一种 shell:

#!/usr/bin/perl
#
my $fn=`find /home -name '$ARGV[0]'`;
chomp $fn;
my $wc=`wc -l '$fn'`;
print "$wc\n";
system ("your curl command");

【讨论】:

  • 哥们,当我要求 perl 时,你给了我一个 bash,是的,伙计,有不同的目录要运行,所以这对我来说很难,我被卡住了
  • 耐心... :-) 需要先测试 perl 版本。但是:您会看到 bash 对于像这样的简单自动化任务要容易得多。
  • 是的 bash 很简单,我一开始都是在 bash 上做的,但是我的老板要我使用 perl :(
  • 它说,未定义的子程序 &File::Find::name
  • 这很奇怪。它适用于我的系统(Linux Mint)。我尝试了一些明显的错字,但我无法重现您的信息。此外,File::Find 应该是核心发行版的一部分。
【解决方案2】:

以下代码 sn-p 演示了实现所需结果的多种方法之一。

代码采用一个参数,一个要在文件data.list 内的所有子目录中查找的单词。并在终端打印出找到的文件列表。

代码使用子程序lookup($dir,$filename,$search),一旦遇到子目录就会递归调用自己。

搜索从当前工作目录开始(有问题没有指定一个目录作为起点)。

use strict;
use warnings;
use feature 'say';

my $search = shift || die "Specify what look for";
my $fname  = 'data.list';

my $found = lookup('.',$fname,$search);

if( @$found ) {
    say for @$found;
} else {
    say 'Not found';
}

exit 0;

sub lookup {
    my $dir    = shift;
    my $fname  = shift;
    my $search = shift;

    my $files;
    my @items = glob("$dir/*");

    for my $item (@items) {
        if( -f $item && $item =~ /\b$fname\b/ ) {
            my $found;
            open my $fh, '<', $item or die $!;
            while( my $line = <$fh> ) {
                $found = 1 if $line =~ /\b$search\b/;
                if( $found ) {
                    push @{$files}, $item;
                    last;
                }
            }
            close $fh;
        }
        if( -d $item ) {
            my $ret = lookup($item,$fname,$search);
            push @{$files}, $_ for @$ret;
        }
    }

    return $files;
}

script.pl search_word运行

输出样本

./capacitor/data.list
./examples/data.list
./examples/test/data.list

参考: glob, Perl file test operators

【讨论】:

  • 谢谢你,但我不能像它的公司 linux 那样使用这个功能
  • say 是 perl 自 5.10 版以来的一部分。或者你是说你使用了更古怪的 perl 版本,所以这个功能不可用?
猜你喜欢
  • 2017-09-29
  • 2015-10-18
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-12
  • 1970-01-01
相关资源
最近更新 更多