filehandle - won't write to a file - perl

I cannot get the script below to write to the file, data.txt, using a FILEHANDLE. Both the files are in the same folder, so that's not the issue. Since I started with Perl, I have noticed to run scripts, I have to use a full path: c:\programs\scriptname.pl and also the same method to input files. I thought that could be the issue and tried this syntax below but that didn't work either...
open(WRITE, ">c:\programs\data.txt") || die "Unable to open file data.txt: $!";
Here is my script. I have checked the syntax until it makes me crazy and cannot see an issue. Any help would be greatly appreciated!. I'm also puzzled, why the die function hasn't kicked in.
#!c:\strawberry\perl\bin\perl.exe
#strict
#diagnostics
#warnings
#obtain info in variables to be written to data.txt
print("What is your name?");
$name = <STDIN>;
print("How old are you?");
$age = <STDIN>;
print("What is your email address?");
$email = <STDIN>;
#data.txt is in the same file as this file.
open(WRITE, ">data.txt") || die "Unable to open file data.txt: $!";
#print information to data.txt
print WRITE "Hi, $name, you are \s $age and your email is \s $email";
#close the connection
close(WRITE);
How I solved this problem solved.
I have Strawberry Perl perl.exe installed on the c: drive, installed through and using the installer with a folder also on c with my scripts in, which meant I couldn't red/write to a file (directional or using functions, ie the open one) and I always had to use full paths to launch a script. I solved this problem after a suggestion of leaving the interpreter installed where it was and moving my scripts file to the desktop (leave the OS command in the first line of the script where it is as the interpreter is still in the same place it was initially). Now I can run the scripts with one click and read/write and append to file with CMD prompt and using Perl functions with ease.

Backslashes have a special meaning in double-quoted strings. Try escaping the backslashes.
open(WRITE, ">c:\\programs\\data.txt") || die ...;
Or, as you're not interpolating variables, switch to single quotes.
open(WRITE, '>c:\programs\data.txt') || die ...;
It's also worth using the three-argument version of open and lexical filehandles.
open(my $write_fh, '>', 'c:\programs\data.txt') || die ...;

you must use "/" to ensure portability, so: open(WRITE, ">c:/programs/data.txt")
Note: I assume that c:/programs folder exists

You may want to try FindBin.
use strict;
use warnings;
use autodie; # open will now die on failure
use FindBin;
use File::Spec::Functions 'catfile';
my $filename = catfile $FindBin::Bin, 'data.txt';
#obtain info in variables to be written to data.txt
print("What is your name?"); my $name = <STDIN>;
print("How old are you?"); my $age = <STDIN>;
print("What is your email address?"); my $email = <STDIN>;
{
open( my $fh, '>', $filename );
print {$fh} "Hi, $name, you are $age, and your email is $email\n";
close $fh;
}

If you have an access problem when you try to print to data.txt you can change that line to:
print WRITE "Hi, $name, you are \s $age and your email is \s $email" || die $!;
to get more information. A read only file will cause this error message:
Unable to open file data.txt: Permission denied at perl.pl line 12, <STDIN> line 3.

Related

How Can I output the response to text file and open the text file when done

I want to modify a Perl script to save the result to text file output.txt and open the results output.txt when task is done
I have tried used "use strict;
use warnings;" and other methods but I keep getting an errors' The Last error was "Couldn't open output.txt"
#!/usr/bin/perl
use HTTP::Request;
use LWP::UserAgent;
system('cls');
system "color c";
print"\n";
print" |||||||||||||||||Robots scanner|||||||||||||||||||||";
print "\n";
print " Scan Your site Site\n\n Example: www.test.com \n\n-> ";
$site=<STDIN>;
chomp $site;
if($site !~ /http:\/\//) { $site = "http://$site/"; };
print "\n";
#path = ('robotx.txt','robots.txt','robot.txt','search',);
foreach $robots(#path){
$url = $site.$robots;
$req = HTTP::Request->new(GET=>$url);
$useragent = LWP::UserAgent->new();
$response = $useragent->request($req);
my $filename = 'report.txt';
open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
if ($response->is_success){
print ">>>>>>Robots Found !!!>>>: $url\n";
print $fh "out put has been generated by perl\n"; # THIS DOESN'T WORK THE report.txt is empty
print "done\n";
}else{
print "NotFound : $robots\n";
print "done\n";
# I want to open the file from windows explorer automatically here when its done
close $fh;
}
}
after running cmd as Admin , as you can see the report.txt file shows empty
I expect to see the out put of the Response
I also want perl to open the report.txt ( without going to windows explorer and opening it manually by the user ) I want it automatically open when its done but I wasn't able to achieve that.
Thanks!
Seems you're always overwriting your report file.
Your open is inside the foreach loop. The loop is done 4 times. You will only receive the output of the last run as the first 3 file creations will be overwritten by the last one.
You should put the open and close outside the loop.
If you only need the first result, you can leave, the loop by putting a last statement at the end of the "then-part" of your if.
Try changing open(my $fh, '>', $filename) to open(my $fh, '>>', $filename) (two arrows instead of one. This will add each new entry instead of delete the last one.
Here are some answers on opening Windows files with Perl:
How to run an executable file using Perl on Windows XP?

Are there any gotchas with open(my $f, '<:encoding(UTF-8)', $n)

I am having a problem that I am unable to reproduce in a manner suitable for Stackoverflow although it's reproducable in my production environment.
The problem occors in a Perl script that, among others, iterates over a file that looks like so:
abc-4-9|free text, possibly containing non-ascii characters|
cde-3-8|hällo wörld|
# comment
xyz-9-1|and so on|
qrs-2-8|and so forth|
I can verify the correctness of the file with this Perl script:
use warnings;
use strict;
open (my $f, '<:encoding(UTF-8)', 'c:\path\to\file') or die "$!";
while (my $s = <$f>) {
chomp($s);
next unless $s;
next if $s =~ m/^#/;
$s =~ m!(\w+)-(\d+)-(\d+)\|([^|]*)\|! or die "\n>$s<\n didn't match on line $.";
}
print "Ok\n";
close $f;
When I run this script, it won't die on line 10 and consequently print Ok.
Now, I use essentially the same construct in a huge Perl script (hence irreproducable for Stackoverflow) and it will die on line 2199 of the input file.
If I change the first line (which is completely unrelated to line 2199) from something like
www-1-1|A line with some words|
to
www-1-1|x|
the script will process line 2199 (but fail later).
Interestingly, this behaviour was introduced when I changed
open (my $f, '<', 'c:\path\to\file') or die "$!";
to
open (my $f, '<:encoding(UTF-8)', 'c:\path\to\file') or die "$!";
Without the :encoding(UTF-8) directive, the script does not fail. Of course, I need the encoding directive since the file contains non-ascii characters.
BTW, the same script runs without problems on Linux.
On Windows, where it fails, I use Strawberry Perl 5.24
I do not have a full and correct explanation of why this is necessary, but you can try opening the file with
'<:unix:encoding(UTF-8)'
This may be related to my question "Why is CRLF set for the unix layer on Windows?" which I noticed when I was trying to figure out stuff which I ended up never figuring out.

Open file in perl and STDERR contents problems

I'm trying to write some unit tests for a perl file uploading script. I'm still pretty new to perl so I'm having some issues achieving the outcome I expect from my code.
Basically my thought process is that I can pass a test_only attribute along with the request that will tell the script to just grab a file already on the system rather than try to use an uploaded file.
I created a test file and put it in my output/tmp directory. I made sure to set its permissions to 775. Its just a simple .txt file that says "I am a test file".
What I expect to happen currently is that when I run my test script I should see the contents of the file printed out to the error log as well as some reference to the buffer(so I can verify the file is being opened properly). However, this is not happening, nothing is being put in the error log. I'm wondering if the file is being opened properly?
I'm sure I'm just missing something fundamental about how perl opens files. Any help will be appreciated. Thanks :)
This is the appropriate snippet of my code:
my $test_only = 1;
my $tmp_uploads_path = "/home/my_instance/output/tmp/";
if($test_only)
{
#put simulated file handle and file name here
$file = "";
$file_name = "test_file.txt";
}
else
{
$file = $q->upload('file')
|| die "No file data sent\n $!";
$file_name = $q->param('file_name')
|| die "No file_name sent\n $!";
}
########
#SAVE THE UPLOAD
########
my $bufsize = 1024;
my $buffer = '';
open(my $TMPFILE, ">".$tmp_uploads_path.$file_name);
binmode $TMPFILE;
print STDERR "=> ".Dumper($TMPFILE)."\n";
while(read ($TMPFILE, $buffer, $bufsize)){
print STDERR "=> ".Dumper($TMPFILE)."\n";
print STDERR "=> ".Dumper($buffer)."\n";
print $TMPFILE $buffer;
}
close($TMPFILE);
You opened the $TMPFILE for writing, due to the > mode. Therefore, you cannot read from it.
You should always put use strict; use warnings; at the top of your scripts, this would have alerted you to this problem!
You should open files like
my $name = ...;
open my $fh, "<", $name or die "Can't open $name: $!";
or
use autodie;
open my $fh, "<", $name;
That is, do proper error handling, and use the three-arg variant of open: handle, mode and name (don't concat mode and name, except on ancient perls).
I am also suprised that you are using read. You can get a similar effect by
local $/ = \$bufsize;
while (defined(my $buffer = <$TMPFILE>)) { ... }

perl unable to copy contents of file and print it

I need to read/copy the contents of a file(test.pl) just as the way it is formatted and email it.
I am using the following code but I am unable to print anything out.
I get this error even though the file exists in the same directory.
Failed: No such file or directory
Code:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
open my $fh, '<', 'test.pl '
or die "Failed: $!\n";
my $text = do {
local $/;
<$fh>
};
close $fh
or die "Failed again: $!\n";
print $text, "\n";
It looks like there is an extra space in the filename you are trying to open. In your open statement, try changing 'test.pl ' to 'test.pl'.
if you are going to read files names from STDIN (user's input), you may want to trim them either by using regex (s/^\s+//....) or Text::Trim among other validations.

How to read multiple files from a directory, extract specific strings and ouput to an html file?

Greetings,
I have the following code and am stuck on how I would proceed to modify it so it will ask for the directory, read all files in the directory, then extract specific strings and ouput to an html file? Thanks in advance.
#!/usr/local/bin/perl
use warnings;
use strict;
use Cwd;
print "Enter filename: "; # Should be Enter directory
my $perlfile =STDIN;
open INPUT_FILE, $perlfile || die "Could not open file: $!";
open OUTPUT, '>out.html' || die "Could not open file: $!";
# Evaluates the file and imports it into an array.
my #comment_array = ;
close(INPUT_FILE);
chomp #comment_array;
#comment_array = grep /^\s*#/g, #comment_array;
my $comment;
foreach $comment (#comment_array) {
$comment =~ /####/; #Pattern match to grab only #s
# Prints comments to screen
Print results in html format
# Writes comments to output.html
Writes results to html file
}
close (OUTPUT);
Take it one step at a time. You have a lot planned, but so far you haven't even changed your prompt string to ask for a directory.
To read the entered directory name, your:
my $perlfile =STDIN;
gives an error (under use strict;). Start by looking that error up (use diagnostics; automates this) and trying to figure out what you should be doing instead.
Once you can prompt for a directory name and print it out, then add code to open the directory and read the directory. Directories can be opened and read with opendir and readdir. Make sure you can read the directory and print out the filenames before going on to the next step.
a good starting point to learn about specific functions (from the cmd line)
perldoc -f opendir
However, your particular problem is answered as follows, you can also use command line programs and pipe them into a string to simplify file handling ('cat') and pattern matching ('grep').
#!/usr/bin/perl -w
use strict;
my $dir = "/tmp";
my $dh;
my #patterns;
my $file;
opendir($dh,$dir);
while ($file = readdir($dh)){
if (-f "$dir/$file"){
my $string = `cat $dir/$file | grep pattern123`;
push #patterns, $string;
}
}
closedir($dh);
my $html = join("<br>",#patterns);
open F, ">out.html";
print F $html;
close F;