Reputation: 135
I want to look for a string in all the files in a directory in perl. But the following code is not working
if ($^O eq "MSWin32") {
my @results = `findstr /s "Hello" /d:\\Testing`;
print "my results \n @results\n";
#or
system('findstr /s "Hello" /d:\\Testing');
}
I am running the script from "C:" and it contains "Testing" directory. For the non windows system it works perfectly fine using grep system command. Please help. Thanks
Upvotes: 1
Views: 1334
Reputation: 8408
You're not using findstr correctly.
findstr /?
)With all those in mind, a working findstr command would be
findstr /s /d:"Testing" *
If you just need the filenames containing matches (not the content of line in the file with the match), use the /m
switch
findstr /s /m /d:"Testing" *
Also the /s
switch is not needed if you don't need recursive searching (e.g. search the subdirectory of C:\Testing)
Another thing to note is that if you use /d:"Testing"
, the first line of the output would be
Testing:
which would end up as the first element in your array. To counter this, you can shift
your array, or better still, change the working directory to Testing in Perl.
The code snippet below shows how I would rewrite this
#!/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";
}
Other notes (god, this post is too long already!):
qx'...'
is somewhat equivalent to `...`
except that whatever is in between is not interpolated.$"
is the separator used for array elements when the array is interpolated within double quotes in a print
or say
(once you get the code working, change its value to see what it does)map
does some processing on each element of the array
s/^/Testing\\/
prefixes each filename with "Testing**" (so that your results will be **relative to C: instead of relative to Testing)chomp
removes trailing whitespace character (e.g. newline) from the result$_
makes sure that it returns the modified filename (instead of the return value of s///
which is # substitution)You can go one step further and parameterize the folder name ("Testing") and string-to-search in the code, and even get user input for those parameters. But that is left as an exercise to the reader (because I'm le tired and the post is already too long)
Upvotes: 1
Reputation: 139521
Your invocation of findstr
is hanging because you did not provide a glob pattern to match against.
Consider using code similar to
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";
}
}
Notes:
*.*
at the end of the command.findstr
ran successfully by examining $?
rather than blindly assuming success./p
option tells findstr
to skip files with unprintable characters. You may or may not want to retain this option.Upvotes: 0
Reputation: 118605
findstr /s "Hello" /d:\\Testing
specifies a UNC path, i.e., looking for files on a remote host named Testing
. Use a single backslash to specify a directory. But I'm not sure that that's what you want either
findstr /s "Hello" /d:\Testing
specifies the directory Testing
at the root of the current drive, which is to say C:\Testing
. If you want to specify the directory Testing
under the current directory, then it's
findstr /s "Hello" /d:Testing
and if you're also finding findstr
to be pretty tempermental, you may have better luck with something like
findstr /s "Hello" /d:Testing\*
But of course, the real solution is to install the DWIM tool ack
, your inability to use CPAN libraries notwithstanding.
Upvotes: 0
Reputation: 1
I think you might want to try http://search.cpan.org/~mneylon/File-Grep-0.02/Grep.pm
Also, when writing functions cross platform for Linux and Windows, I tend to include this at the top of my scripts just to cover anything I may do that is windows specific:
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
Upvotes: 0
Reputation: 3780
Judging by the findstr
documentation, you appear to have your findstr
options a bit mixed up; /d
doesn't take an argument, and it looks like switches are required to appear before the search string and the start path. So try this:
findstr /d /s "Hello" \\Testing
in place of the findstr
command you're currently using, and you may find better results.
Upvotes: 0