elsoja
elsoja

Reputation: 1757

Error when opening a file located in the same directory

I just started learning Perl and i'm having a problem related to opening a file that is in the same directory as my program.

#!/usr/bin/perl -w

$proteinfilename = 'NM_021964fragment.pep';

open(PROTEINFILE, $proteinfilename) or die "Can't write to file '$proteinfilename' [$!]\n";

$protein = <PROTEINFILE>;

close(PROTEINFILE);

print "Essa é a sequência da proteína:\n";
print $protein, "\n";

exit;

When I specify the directory of the file, changing from 'NM_021964fragment.pep' to '/Users/me/Desktop/programa/NM_021964fragment.pep', the program works. But shouln't it work even without me specifying the directory, as the program and the file are in the same folder?

Upvotes: 4

Views: 698

Answers (2)

ikegami
ikegami

Reputation: 385496

Relative paths are relative to the current work directory, not the script's directory. When the script worked, they happened to be the same. But as you found, that's not always the case. You could use the following to achieve the behaviour you describe:

use Cwd         qw( realpath );
use Path::Class qw( file );

my $script_dir = file(realpath($0))->dir;
my $input_file = $script_dir->file('NM_021964fragment.pep');

Upvotes: 1

TLP
TLP

Reputation: 67900

If you are doing a simple file read, you can use the <> diamond operator for simplicity.

use strict;
use warnings;

my $protein = <>;
print "Essa é a sequência da proteína:\n";
print "$protein\n";

And use the script like so:

perl script.pl NM_021964fragment.pep

This will force you to use the correct paths, assuming you use tab autocomplete when you run your script.

Using a command-line argument this way is somewhat unsafe, since it is possible to execute arbitrary code through unprotected open commands. You can use the module ARGV::readonly to prevent such things. Or simply use the code itself, it is rather simple:

for (@ARGV){
   s/^(\s+)/.\/$1/;    # leading whitespace preserved
   s/^/< /;            # force open for input
   $_.=qq/\0/;         # trailing whitespace preserved & pipes forbidden
};

Upvotes: 2

Related Questions