Hello,
I would need your help,
I have a Perl code that makes a folder structure, it reads a txt and creates the folders
Now I have an issue I have to go through this folder structure and insert a file delete_me txt is yhe lowest level, and I have many lowest levels.
How do I search?

Now I have an issue I have to go through this folder structure and insert a file delete_me txt is yhe lowest level, and I have many lowest levels.

By "lowest level folder" do you mean any folder that does not have sub-folders?

yes
01 A
02B
03C\01cc
04D\01dd
04D\02dd

I would have to insert at this point in all of them

use File::Find;

### Declare your path
my $dir = "d:/muthu";

### travel the $dir path
find(\&get_lowest_folder, $dir);

### Now the lowest level folder info in array @low
print "\n$_" for @low;


sub get_lowest_folder
{
	if (-d) # check current path is a directory
	{
		### save current directory name into a array
		push @file, $File::Find::name;

		### check the current dir path is not match the
		### previous directory path and save the previous
		### directory path into a array (@low)
		push @low, $file[$#file-1] if ($file[$#file] !~ m{$file[$#file-1]});
	}
}

$dir="D:\muthu";

CURRENT DIR !~ /PREVIOUS DIR/
(i.e) $file[$#file] !~ /$file[$#file-1]/
S1: d:\muthu\demo !~ /d:\muthu/ # False statement
S2: d:\muthu\dani !~ /d:\muthu\demo/ # True statement

So Now you get the lowest folder : d:\muthu\demo

Another way to do it is to open each directory found by File::Find as a directory handle to see it contains subdirectories.

#!/usr/bin/perl
#LastSubdirs02.pl
use 5.006;
use strict;
use warnings;

use File::Find;
find( \&print_lowest_dirs, '/home/david/Programming' );

sub print_lowest_dirs {
	if (-d $File::Find::name) {
		my $dir = $File::Find::name;
		if (not has_subdir($dir)) {
			print "$dir \n";
		}
	}
}

sub has_subdir {
	my $dir = $_[0];
	opendir DH, $dir or die "Failed to open $dir: $!";
	
	while ($_ = readdir(DH)) {
		next if $_ eq "." or $_ eq "..";
		return 1 if -d $dir . '/' . $_; # Is the full path plus the filename a directory?
	}
	return 0; # Did not find any subdirectory in this directory
}

k_manimuthu, I think your script overlooks the last directory entered by the File::Find. I understand that your subroutine compares each current directory with the previous, and prints the previous if it is not equal to the first part of the current. But I don't think the last directory entered by the File::Find gets pushed into @low.

Comments
Very Good Analyze

Hi David,

What do you told that’s absolutely right. When I checked my script, I looked into 1, 2, 3, 4 ….. I missed out to check the N'th term. Thanks for your point out.

-Mani Muthu

Edited 6 Years Ago by k_manimuthu: n/a

Using File::Find and filtering the result is a good approach, but the following script having a subroutine that calls itself also seems to work.

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

sub print_dirs_without_subdirs {
    #This subroutine calls itself for each subdirectory it finds.
    #If it finds no directories, it prints the name of the directory in which
    # it is looking, $dir.
    my $dir = $_[0];
    opendir DH, $dir or die "Failed to open $dir: $!";
    my @d;
    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
        print "$dir\n";
        return;
    }
    foreach (@d) {
        print_dirs_without_subdirs($_); #Look for directories in directory
    }
}

Hello,

I'm new to perl, how do I modify your code to find third level folder under a given Base_Dir?

Thanks

Hello,

I'm new to perl, how do I modify your code to find third level folder under a given Base_Dir?

Thanks

There are more than one scripts in this topic that could be modified to do what you want, but some would take a lot more work than others.

If I needed to find the third level folder under a given Base_Dir for myself or my boss at work, I would prefer to do it in two steps:

  1. use File::Find module as in the examples above, but only to print ALL subdirectories
  2. Write a second Perl script that reads the list of subdirs from Step 1 and decides which ones have the desired level of depth

By breaking it into two steps you get to examine the output from Step 1 and first manually pick out the lines you want your second script to find, and then write and test your second script until you are satisfied it finds exactly what you want from the data produced by your first script. When you want to use your two scripts together you can run them both from the command line with a piping symbol between them to direct the output (STDOUT) of the first script into the input (STDIN) of the second.

This article has been dead for over six months. Start a new discussion instead.