[ top-posting fixed ]
"R. Joseph Newton" wrote:
>
> Adriano Allora wrote:
>
> > I need to know, in the @ARGV, when a string is the name of a directory.
> > More precisely I'd like to write a script that:
> >
> > processes the files of the textes in a dir
> > extracts the list of the sub-directories in a dir
> > in each sub-dir processes the files of the textes
> > extracts the list of the sub-directories
> > in each sub-dir processes the files of the textes
> > extracts the list
>of the sub-directories
> > and go
>on...
>
> Hi Adriano,
>
> Here is a start. You might have to adapt it somewhat for youe specific
> uses. It originated from a proplem Paul posed concernig a search for files
> of a given name on a single level of a directory tree, and greww from there.
> It's taken on a bit of random testion g code also. The indent function was
> born with this program, but never used in it. It has since been moved to a
> *.pm file.
>
> #!/usr/bin/perl
> use warnings;
> #use strict;
Why disable strict?
> # Utility to search filenames and text in a given folder and all subdirectoies
> # Usage: DirTreeTest.pl -f|-t $baseDir $soughtFile
> # If the first parameter is -f, the utility returns all folders containg the given
>file.
> # If the first parameter is -t, the utility returns all files containg the given
>text.
>
> my $option = $ARGV[0];
> my $baseDir = $ARGV[1];
> my $soughtFile = $ARGV[2];
> my $indentSize = 2;
> if ($option eq "-f") {
> ListDirectoriesContainingFile ($ARGV[1], $ARGV[2], 0);
Why not:
ListDirectoriesContainingFile ($baseDir, $soughtFile, 0);
In fact, since the contents of $soughtFile don't change, why pass it to
the subroutine at all?
> } elsif ($option eq "-t") {
> ListFilesContainingText ($ARGV[1], $ARGV[2], 0);
> } else {
> die "You must specify either -f or -t";
> }
>
> sub ListDirectoriesContainingFile {
> my $currentDir = $_[0];
> my $targetFile = $_[1];
> my $indentation = $_[2];
> my $DIR;
> opendir $DIR, $currentDir or die "Cannot opendir $currentDir: $!";
> my $testFile = "";
> while (my $file = readdir $DIR ) {
> $testFile = "$currentDir\\$file";
^^
The backslash will only work on some operating systems. How can you be
sure the OP is using that particular OS?
> if ( -d $testFile) {
> my $go;
> if ($go = ($file ne "." and $file ne "..")) {
^^^^^
What is this variable for?
> if (-e "$testFile\\$targetFile") {
> print "Found in:\n---=>>$testFile\n";
> }
> ListDirectoriesContainingFile("$testFile",
> $targetFile, $indentation + 2);
> }
> }
> }
> }
>
> sub ListFilesContainingText {
> my $currentDir = $_[0];
> my $targetText = $_[1];
> my $indentation = $_[2];
> chomp $targetText;
> my $DIR;
> print "current directory is $currentDir\n";
> opendir $DIR, $currentDir or die "Cannot opendir $currentDir: ";
> my $testFile = "";
> my $file = "";
> while (defined($file = readdir $DIR) and $file ne "") {
^^^^^^^^^^^
While I won't say that it is impossible, I would say that it is HIGHLY
improbable that a file system would store a zero length file name.
> $testFile = "$currentDir\\$file";
> if ( $testFile and (-d $testFile)) {
> if ($file eq "\." || $file eq "\.\.") {;
^^ ^^^^
Periods don't have to be backslashed in strings. Better to use unless
instead of an empty if block.
> } else {
> ListFilesContainingText($testFile, $targetText, ($indentation + 2));
> }
> }
> else {
> #print "file $testFile checked\n";
> if ($file =~ /\..*\./) {
> print " ~~~> $testFile is ugly in form\n";
^^^^^^^^^^^^
Why is this "ugly"? Why should we care?
> }
> open (SEEK_FILE, $testFile) or print "can not open $testFile\n";
> my $lineNumber = 1;
Perl provides the current line number in the $. variable (if you use a
proper while loop.)
> my $CurrentLine = <SEEK_FILE>;
> my $IsIt;
> while ($CurrentLine) {
> if ($IsIt = ($CurrentLine =~ /\b$targetText\b/)) {
What happens if $targetText contains regular expression special
characters like '.', '*', '(', etc.?
> print "--=>> $testFile: $lineNumber \n";
> print " |$CurrentLine \n";
> #continue;
> }
> $lineNumber++;
> $CurrentLine = <SEEK_FILE>;
> }
> close SEEK_FILE;
> }
> }
> }
>
> sub indent {
> my ($indentation, $textString) = @_;
> my $indent = "";
> $oneSpace = " ";
> for ($i = 0; $i < $indentation; $i++) {
> $indent = $indent.$oneSpace;
> }
> print "$indent$textString"; print "\n";
> }
Why re-invent several wheels which are already provided with the
standard Perl distribution?
#!/usr/bin/perl
use warnings;
use strict;
use File::Find;
use Getopt::Std;
# Utility to search filenames and text in a given folder and all
subdirectoies
# Usage: DirTreeTest.pl -f|-t $baseDir $soughtFile
# If the first parameter is -f, the utility returns all folders containg
the given file.
# If the first parameter is -t, the utility returns all files containg
the given text.
sub usage {
print STDERR <<USAGE;
Usage: $0 -f filename directory
return all folders containg the given file.
$0 -t "text" directory
return all files containg the given text.
USAGE
exit 0;
}
my %opts;
getopts( 'f:t:', \%opts ) or usage;
$opts{'f'} and $opts{'t'} and usage; # one option only
my $baseDir = shift or usage;
find( sub {
if ( $opts{'f'} and $_ eq $opts{'f'} ) {
print "Found in:\n---=>>$File::Find::dir\n";
}
elsif ( $opts{'t'} ) {
return unless -f;
{ # local scope for @ARGV and $_
local ( @ARGV, $_ ) = $File::Find::name;
while ( <> ) {
if ( index( $_, $opts{'t'} ) >= 0 ) {
print "--=>> $ARGV: $.\n";
print " |$_\n";
}
}
}
}
}, $baseDir );
__END__
John
--
use Perl;
program
fulfillment
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]