使用perl中的Findstr搜索目录

时间:2013-07-18 21:18:45

标签: windows perl findstr

我想在perl目录中的所有文件中查找字符串。但是以下代码无效

if ($^O eq "MSWin32") {
my @results = `findstr /s "Hello" /d:\\Testing`;
print "my results \n @results\n";
#or 
system('findstr /s "Hello" /d:\\Testing');
}

我从“C:”运行脚本,它包含“Testing”目录。 对于非Windows系统,使用grep system命令可以很好地工作。 请帮忙。谢谢

5 个答案:

答案 0 :(得分:1)

正确使用 findstr

  1. 顺序很重要:开关/选项应该在参数之前(搜索字符串)(参见findstr /?的输出)
  2. 指定要搜索的文件的参数是必需参数(此参数允许使用通配符)。
  3. 考虑到所有这些,一个有用的 findstr 命令将是

    findstr /s /d:"Testing" *
    

    如果您只需要包含匹配项的文件名(不是匹配文件中的行内容),请使用/m开关

    findstr /s /m /d:"Testing" *
    

    如果您不需要递归搜索(例如,搜索 C:\ Testing 的子目录),则不需要/s开关

    另外需要注意的是,如果使用/d:"Testing",输出的第一行将是

    Testing:
    

    最终会成为数组中的第一个元素。要解决此问题,您可以shift您的阵列,或者更好的是,将工作目录更改为Perl中的测试

    下面的代码片段显示了我将如何重写此

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    if ($^O eq "MSWin32") {
        chdir("Testing");
        my @results = qx'findstr /s /m "Hello" *';
        local $" = ", ";
        @results = map { s/^/Testing\\/; chomp; $_ } @results;
        chdir("..");
        print "my results \n@results\n";
    }
    

    其他说明(上帝,这篇文章已经太长了!):

    • qx'...'在某种程度上等同于`...`,除了介于两者之间的内容不是插值的。
    • $"是用于数组元素的分隔符,当数组在printsay中用双引号插值时(一旦你得到代码工作,改变它的值看看是什么它确实)
    • map对数组的每个元素进行一些处理
      • s/^/Testing\\/为每个文件名添加“测试**”前缀(这样您的结果将相对于C:而不是相对于测试)
      • chomp从结果
      • 中删除尾随空格字符(例如换行符)
      • 最后一个$_确保它返回修改后的文件名(而不是s///的返回值,即#substitution)

    您可以更进一步,在代码中参数化文件夹名称(“测试”)和字符串到搜索,甚至可以获取这些参数的用户输入。但这留给了读者一个练习(因为我累了,帖子已经太长了)

答案 1 :(得分:0)

我想你可能想尝试http://search.cpan.org/~mneylon/File-Grep-0.02/Grep.pm

此外,在为Linux和Windows编写跨平台功能时,我倾向于将其包含在我的脚本顶部,以涵盖我可能做的任何特定于Windows的功能:

BEGIN { # include additional Win32 specific modules when running on MS platforms
  if ($^O =~ /Win32/) {
    require Win32::AdminMisc; import Win32::AdminMisc;
    require Win32::API; import Win32::API;
    require Win32::GUI; import Win32::GUI;
    $wincon=Win32::GUI::GetPerlWindow();
  }
}

# your code starts here

答案 2 :(得分:0)

根据the findstr documentation判断,您的findstr选项似乎有点混乱; /d不接受参数,看起来需要在搜索字符串和起始路径之前出现切换。所以试试这个:

findstr /d /s "Hello" \\Testing

代替您当前使用的findstr命令,您可能会发现更好的结果。

答案 3 :(得分:0)

findstr /s "Hello" /d:\\Testing

指定UNC路径,即在名为Testing的远程主机上查找文件。使用单个反斜杠指定目录。但我不确定那是你想要的

findstr /s "Hello" /d:\Testing

指定当前驱动器根目录的目录Testing,即C:\Testing。如果要在当前目录下指定目录Testing,那么

findstr /s "Hello" /d:Testing

如果你也发现findstr很温和,你可能会有更好的运气,比如

findstr /s "Hello" /d:Testing\*

但是,当然,真正的解决方案是安装DWIM工具ack,尽管你的inability to use CPAN libraries

答案 4 :(得分:0)

您的findstr调用暂停,因为您没有提供匹配的glob模式。

考虑使用类似于

的代码
if ($^O eq "MSWin32") {
  my @results = `findstr /s /p /d:C:\\Testing "Hello" *.*`;
  die "$0: findstr failed" if $?;

  if (@results) {
    print @results;
  }
  else {
    warn "$0: no results\n";
  }
}

注意:

  • 最大的变化是在命令末尾添加了*.*
  • 通过检查findstr检查$?是否成功运行,而不是盲目地假设成功。
  • /p选项告诉findstr跳过包含不可打印字符的文件。您可能想要也可能不想保留此选项。