[ 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]