-5

My file's name is "rootpass" and I am trying to read it like this,

my $rootpass;
my $passfile = "$jobDir/\rootpass";
print "file name = $passfile\n";
if( -e $passfile)
{    
    open ROOTPASS, '$passfile';
    $rootpass = <ROOTPASS>;
    print "$rootpass\n";
}
else
{
    print "No read permissions on password file $passfile\n";
    exit 1;
}

I get an error like this,

Unsuccessful stat on filename containing newline at ReadFile.pl line 106. 

106 is the if() line. I have tried the following,

  1. made it my $passfile = "$jobDir\/rootpass"; to escape the escape char
  2. made it my $passfile = "$jobDir//rootpass"; to escape the 'r' so it wont think I have a return char in the file name

How do I read the file whose name is rootpass under the directory name contained in the variable $jobDir?

Mat
  • 202,337
  • 40
  • 393
  • 406
quickdraw
  • 247
  • 1
  • 2
  • 12
  • 2
    Why do you think you need to escape the `r` in the first place? – Sobrique Feb 29 '16 at 11:05
  • 1
    That's more likely because you forgot to `chomp` when you read it. – Sobrique Feb 29 '16 at 11:16
  • Because I was getting errors saying that there is a new line in the name and when i print the file name, this is the output,file name = /home/test/files/10.6.502.0 ootpass Unsuccessful stat on filename containing newline at ReadFile.pl line 106. No read permissions on password file /home/test/files/10.6.502.0 ootpass. The /home/test/files/10.6.502.0 is the path to the file. And rootpass is being printed in a new line as ootpass – quickdraw Feb 29 '16 at 11:17
  • You ADDED newline. `\r` IS new line. Remove slash. Also remove `'` around `$rootpass`. It doesn't needs quoting at all and single quotes don't do variable expansion. – Oleg V. Volkov Feb 29 '16 at 11:18
  • You no need to escape the `r`. You can just use it as it is. – Karthikeyan.R.S Feb 29 '16 at 11:18
  • Are you saying that "my $passfile = "$jobDir/rootpass"; will make it work? And I can open the file like open ROOTPASS, '$passfile'; ? – quickdraw Feb 29 '16 at 11:21
  • Just `open ROOTPASS, $passfile;`. `'` actually will break it because you'll be looking for file literally named "$passfile", not "rootpass". – Oleg V. Volkov Feb 29 '16 at 11:22
  • I tried that and I get the following, file name = /home/test/files/10.6.502.0 /rootpass Unsuccessful stat on filename containing newline at ReadFile.pl line 106 – quickdraw Feb 29 '16 at 11:22
  • The "/home/test/files/10.6.502.0" and " /rootpass" are in two different lines. I am not able to write the comment like that here.. – quickdraw Feb 29 '16 at 11:24
  • I tried not check -e on the file name and directly opened it and this is the error I get, Unsuccessful open on filename containing newline at ReadFile.pl line 108. readline() on closed filehandle ROOTPASS at ReadFile.pl – quickdraw Feb 29 '16 at 11:27
  • Where do you get `$jobDir` from? Any chance _that_ contains a new line? – Sobrique Feb 29 '16 at 11:28
  • I create $jobDir as, $jobDir = "/home/test/files/$process_build"; and $process_build will be a string like 10.0.9.7 or something similar – quickdraw Feb 29 '16 at 11:35
  • I get the same error even after I changed the name to "passroot" instead of "rootpass"!!!! There is some other issue.. – quickdraw Feb 29 '16 at 11:41
  • I got the issue! After I changed the statement, my $passfile = "$jobDir/\rootpass"; to my $passfile = '$jobDir/\rootpass'; Issue went away! Can someone explain what happened? – quickdraw Feb 29 '16 at 11:42
  • This reminds me of [this discussion](http://stackoverflow.com/a/35535728/5830574) a few days ago. – PerlDuck Feb 29 '16 at 13:26
  • That's because the single quotes `'` (as opposed to the double quotes `"`) do not interpolate variables inside, i.e. now you are looking for a file called (literally!) `dollar-jay-ouh-bee-Dee-i-arr-slash-backslash-arr-ouh-ouh`... And that file doesn't exist. – PerlDuck Feb 29 '16 at 13:32

2 Answers2

0

A lot of good comments on the original question, but you also:

  • shouldn't be using global file handles
  • should be using three-argument open
  • are checking if the file exists, but give the error message that it's not readable. If the file exists but isn't readable, your script won't work, without giving a useful error message.

Here's a modern perl version of your script:

use 5.012;      # enables "use strict;" and modern features like "say"
use warnings;
use autodie;    # dies on I/O errors, with a useful error message

my $jobDir = '/path/to/job/directory';

my $passfile = "$jobDir/rootpass";
say "filename: '$passfile'";

# No need for explicit error handling, "use autodie" takes care of this.
open (my $fh, '<', $passfile);
my $rootpass = <$fh>; chomp($rootpass);  # Gets rid of newline
say "password: '$rootpass'";
mscha
  • 6,509
  • 3
  • 24
  • 40
  • Like [`use Modern::Perl`](http://metacpan.org/module/Modern::Perl), a `use VERSION` statement isn't very transparent about what it does, and generally needs commenting to explain why it's there. If you want strictures and `say` then you should write `use strict` and `use feature 'say'` although if you know for sure which version of Perl is required for your program then it can be useful to add a `use VERSION` as well for that version. For instance, `use autodie` wasn't available until Perl v5.14.1, so a `use v5.14.1` statement is more useful than getting `Can't locate diagnostics.pm` message – Borodin Feb 29 '16 at 17:11
  • Don't get too focused on the *modern features* comment. You may feel bang up to date now, but unless you revise your entire code base regularly they won't be "modern" for long (in fact, isn't the word "modern" a little passé?!) and your code will look silly. Just `# For strictures and 'say'` is plenty. No comment on `autodie` is necessary at all, and certainly `# Gets rid of newline` is bloat. I'm sorry, I'm writing a code review when I shouldn't. I hope it's useful anyway – Borodin Feb 29 '16 at 17:17
0

This line

my $passfile = "$jobDir/\rootpass";

will put a carriage-return character—hex 0D—where \r is in the string. You presumable mean just

my $passfile = "$jobDir/rootpass";

The line

open ROOTPASS, '$passfile';

will try to open a file called—literally—$passfile. You want

open ROOTPASS, $passfile;

or, much better

open my $pass_fh, '<', $passfile or die $!;

Here's a summary

use strict;
use warnings;

my $jobdir   = '/path/to/jobdir';
my $passfile = "$jobdir/rootpass";

print "file name = $passfile\n";

open my $pass_fh, '<', $passfile or die qq{Failed to open "$passfile" for input: $!};
my $rootpass = <$pass_fh>;
print "$rootpass\n";

output

file name = /path/to/jobdir/rootpass
Failed to open "/path/to/jobdir/rootpass" for input: No such file or directory at E:\Perl\source\rootpass.pl line 9.
Borodin
  • 126,100
  • 9
  • 70
  • 144