com
com

Reputation: 79

Trying to pass a subdirectory as a parameter in Perl

I have a Perl program to read .html's and only works if the program is in the same directory as the .html's.
I would like to be able to start in different directories and pass the html's location as a parameter. The program (shell example below) traverses the subdirectory "sub" and its subdirectories to look for .html's, but only works when my perl file is in the same subdirectory "sub". If I put the Perl file in the home directory, which is one step back from the subdirectory "sub", it doesn't work.

In the shell, if I type "perl project.pl ./sub" from my home directory, it says could not open ./sub/file1.html. No such file or directory. Yet the file does exist in that exact spot. file1.html is the first file it is trying to read.

If I change directories in the shell to that subdirectory and move the .pl file there and then say in the shell: "perl project.pl ./" everything is ok.

To search the directories, I have been using the File::Find concept which I found here: How to traverse all the files in a directory; if it has subdirectories, I want to traverse files in subdirectories too Find::File to search a directory of a list of files

#!/usr/bin/perl -w
use strict;
use warnings;
use File::Find;

find( \&directories, $ARGV[0]);

sub directories {
    $_ = $File::Find::name;

    if(/.*\.html$/){#only read file on local drive if it is an .html
        my $file = $_;
        open my $info, $file or die "Could not open $file: $!";
        while(my $line = <$info>)  {   

        #perform operations on file
        }
        close $info;
    }
    return;
}

Upvotes: 3

Views: 488

Answers (3)

Dave Sherohman
Dave Sherohman

Reputation: 46245

From the File::Find documentation:

For each file or directory found, it calls the &wanted subroutine. (See below for details on how to use the &wanted function). Additionally, for each directory found, it will chdir() into that directory and continue the search, invoking the &wanted function on each file or subdirectory in the directory.

(emphasis mine)

The reason it's not finding ./sub/file1.html is because, when open is called, File::Find has already chdired you into ./sub/. You should be able to open the file as just file1.html.

Upvotes: 1

simbabque
simbabque

Reputation: 54381

In the documentation of File::Find it says:

You are chdir()'d to $File::Find::dir when the function is called, unless no_chdir was specified. Note that when changing to directories is in effect the root directory (/) is a somewhat special case inasmuch as the concatenation of $File::Find::dir, '/' and $_ is not literally equal to $File::Find::name.

So you actually are at ~/sub already. Only use the filename, which is $_. You do not need to overwrite it. Remove the line:

$_ = $File::Find::name; 

Upvotes: 3

toolic
toolic

Reputation: 62236

find changes directory automatically so that $File::Find::name is no longer relative to the current directory.

You can delete this line to get it to work:

$_ = $File::Find::name;

See also File::Find no_chdir.

Upvotes: 1

Related Questions