Hey guys, quick question, I'm a beginner and put together a grep script that searches for certain content within text files in a directory. The result yields over 600 lines so i want to put them in a file called file.txt.

opendir (DIR, ".") or die "$!";
                                my @files = grep {/^[\w].+/} readdir DIR;
                                close DIR;
                                foreach my $file (@files) {
                                open(FH,"$file") or die "$!";
                                while (<FH>){ 
				if ($_ =~ /^searchtext/) {
open FILE, ">file.txt" or die $!; print FILE "$_";  }
                                }

                                close(FH);
close FILE;
                                }

This isn't currently working, it only puts in the first line in the text file. Can someone please offer a revision? Thanks.

Recommended Answers

All 6 Replies

open FILE, ">file.txt" or die $!;

The above line creates "file.txt". You are using ">" write mode. So the file position is always beginning of the file. At the end of the process you may got only one matched line. To avoid this kind of circumstance you will open the file at "append mode". Try the below code.

open FILE, ">>file.txt" or die $!;

Thanks for the help!

One last bit of advice, I'm currently using a .bat file (I have 692 files spread over 15 folders) and placing them all into one folder. The xcopy command, however, only moves half of the files?

Is there a better way using perl to do some sort of recursive grep on the multiple folders so I don't have to move all my data into one folder to begin with? If it helps any, the name of the 15 folders always stays the same. If you could please demonstrate with this code I'd appreciate it:

opendir (DIR, ".") or die "$!";
	my @files = grep {/^[\w].+/} readdir DIR;
	close DIR;
	foreach my $file (@files) {
	open(FH,"$file") or die "$!";
		while (<FH>){ 
		if ($_ =~ /^TagString=V3/) {
		open FILE, ">>file.txt" or die $!; print FILE "$_";  }
		}

			close(FH);
			close FILE;
                                }

You could create a subroutine to which you pass each directory name and put your code in there. Try running the following first. It has a subroutine called 'something' that prints a message each time it is called. You could put your code in there.

#!/usr/bin/perl
#DoSomethingInDirAndSubdirs.pl
use strict;
use warnings;
my $startdir = '/home/david/Programming';
do_something_in_dir_and_subdirs($startdir);

sub do_something_in_dir_and_subdirs {
    my $dir = $_[0];
    opendir DH, $dir or die "Failed to open $dir: $!";
    my @d;
    my $res = something("Doing something in $dir");
    while ($_ = readdir(DH)) {
        next if $_ eq "." or $_ eq "..";
        my $fn = $dir . '/' . $_;
        if (-d $fn) {
            push @d, $fn;
        }
    }
    if (scalar @d == 0) { #If no directories found, $dir is lowest dir in this branch
        #We're done.
        return;
    }
    foreach (@d) {
        do_something_in_dir_and_subdirs($_); #Look for directories in directory
    }
}

sub something {
    my $msg = $_[0]; #Assign passed argument to variable
    print '-' x 75, "\n";
    print "$msg\n";
}

Thanks D5E5. I'll give that a try. Another simple problem I came across is, I just realized I don't know how to open a different directory?!

opendir (DIR, ".") or die "$!";

to

opendir (DIR, "data/") or die "$!";

I do that and I receive a response saying:
"No such file or directory at a.pl line 5."

opendir (DIR, "data/") or die "$!";
                                my @files = grep {/^[\w].+/} readdir DIR;
                                close DIR;
                                foreach my $file (@files) {
                                open(FH,"$file") or die "$!";
                                while (<FH>){ 
				if ($_ =~ /^searchtext/) {
					open FILE, ">>file.txt" or die $!; print FILE "$_";  }
                                }

                                	close(FH);
					close FILE;
                                }

problem solved. The error was telling me from the get go. Line 5 needed data/$file.
Thanks to Fishmonger.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.