Perl opening dynamically generated files - perl

I am using CGI script for my website. And I have problem with opening a dynamically generated file. Here is the code:
#!/usr/bin/perl
my #output = `/export/es_share/Zhou/./notification_finder.sh range $date $time $range $ulh TestProd1 $actionname`;
my $filen = $output[0];
open(my $result, "<", $filen) or die "Can't open $filen - $!";
Do something with the file...
Always fails, with the output:
Can't open /var/tmp/notification-finder-1375086676-658183725.tmp -
No such file or directory at /var/www/cgi-bin/appsupport/logapp_test/perltest.cgi line X.
While as this succeeds:
#!/usr/bin/perl
open(my $result, "<", /var/tmp/notification-finder-1375086676-658183725.tmp) or die "Can't open $filen - $!";
Do something with the file...
I have also checked if it was the problem of asynchronous execution of the backticks problem, but from my research on stackoverflow it does not seem to be the issue. I also tried this:
#!/usr/bin/perl
my #output = `/export/es_share/Zhou/./notification_finder.sh range $date $time $range $ulh TestProd1 $actionname`;
sleep(10);
my $filen = $output[0];
open(my $result, "<", $filen) or die "Can't open $filen - $!";
Do something with the file...
I have found this similar issue here, but I don't seem to have the same problem as the asker... Thanks for reading this far.

The error indicates there is a newline on the end of $filen, otherwise it would be:
Can't open /var/tmp/notification-finder-1375086676-658183725.tmp - No such file or directory at /var/www/cgi-bin/appsupport/logapp_test/perltest.cgi line XXXXXXXXX.
Remove it with:
chomp $filen;

Related

Perl-Copying file from one location to other but content not copying

I am writing a script in perl where I am creating a file and getting input from user for file but when I am copying that file to other location the file is copying but it is empty only. My code is
# !/usr/bin/perl -w
for($i = 1;$i<5;$i++)
{
open(file1,"</u/man/fr$i.txt");
print "Enter text for file $i";
$txt = <STDIN>;
print file1 $txt;
open(file2,">/u/man/result/fr$i.txt");
while(<file1>)
{
print file2 $_;
}
close(file1);
close(file2);
}
fr1 to fr4 are creating but these are empty. like when I run my code it is asking for input i provide the input and code run without error but still the files are empty. Please help.
in line number 4 I changed < to > also as I thought for creating new file it might need that but still it is not working
You need to close the filehandle that was written to in order to be able to read from that file.
use warnings;
use strict;
use feature 'say';
for my $i (1..4)
{
my $file = "file_$i.txt";
open my $fh, '>', $file or die "Can't open $file: $!";
say $fh "Written to $file";
# Opening the same filehandle first *closes* it if already open
open $fh, '<', $file or die "Can't open $file: $!";
my $copy = "copy_$i.txt";
open my $fh_cp, '>', $copy or die "Can't open $copy: $!";
while (<$fh>) {
print $fh_cp $_;
}
close $fh_cp; # in case of early errors in later iterations
close $fh;
}
This creates the four files, file_1.txt etc, and their copies, copy_1.txt etc.
Please note the compulsory checking whether open worked.
You can't write to a filehandle that's not open for writing. You can't read from a filehandle that's not open for reading. Never ignore the return value of open.
# !/usr/bin/perl
use warnings; # Be warned about mistakes.
use strict; # Prohibit stupid things.
for my $i (1 .. 4) { # lexical variable, range
open my $FH1, '>', "/u/man/fr$i.txt" # 3 argument open, lexical filehandle, open for writing
or die "$i: $!"; # Checking the return value of open
print "Enter text for file $i: ";
my $txt = <STDIN>;
print {$FH1} $txt;
open my $FH2, '<', "/u/man/fr$i.txt" # Reopen for reading.
or die "$i: $!";
open my $FH3, '>', "/u/man/result/fr$i.txt" or die "$i: $!";
while (<$FH2>) {
print {$FH3} $_;
}
close $FH3;
}
I opened the file in write mode using filehandler1 Then i again opened the file in read mode using same filehandler1 then I opened filehandler2 for destiantion So it is working fine for me then.
system("cp myfile1.txt /somedir/myfile2.txt")
`cp myfile1.txt /somedir/myfile2.txt`

Perl Script: sorting through log files.

Trying to write a script which opens a directory and reads bunch of multiple log files line by line and search for information such as example:
"Attendance = 0 " previously I have used grep "Attendance =" * to search my information but trying to write a script to search for my information.
Need your help to finish this task.
#!/usr/bin/perl
use strict;
use warnings;
my $dir = '/path/';
opendir (DIR, $dir) or die $!;
while (my $file = readdir(DIR))
{
print "$file\n";
}
closedir(DIR);
exit 0;
What's your perl experience?
I'm assuming each file is a text file. I'll give you a hint. Try to figure out where to put this code.
# Now to open and read a text file.
my $fn='file.log';
# $! is a variable which holds a possible error msg.
open(my $INFILE, '<', $fn) or die "ERROR: could not open $fn. $!";
my #filearr=<$INFILE>; # Read the whole file into an array.
close($INFILE);
# Now look in #filearr, which has one entry per line of the original file.
exit; # Normal exit
I prefer to use File::Find::Rule for things like this. It preserves path information, and it's easy to use. Here's an example that does what you want.
use strict;
use warnings;
use File::Find::Rule;
my $dir = '/path/';
my $type = '*';
my #files = File::Find::Rule->file()
->name($type)
->in(($dir));
for my $file (#files){
print "$file\n\n";
open my $fh, '<', $file or die "can't open $file: $!";
while (my $line = <$fh>){
if ($line =~ /Attendance =/){
print $line;
}
}
}

perl "or" to go through a list

I have written a small script that goes looking for a file with a certain ID-number in three different folders. My first attempt to do this was this:
open my $fh, "<", "dir1/file.o$ARGV[0]"
or open my $fh, "<", "dir2/file.o$ARGV[0]"
or open my $fh, "<", "dir3/file.o$ARGV[0]"
or die "Couldn't open `file.o$ARGV[0]' for reading: $!";
This resulted in an empty file handle for files in dir2, which I used for testing, and I have now written an elaborate if(...) else if (...) structure to do what I want. But I still don't understand why my first approach didn't work, so I'm hoping for some insights.
My expectation was that it would try to open the first file, if that failed, look at what comes after the or, try to open that file and so on. Where am I going wrong?
Bonus question: Is there an elegant way to do this?
You're duplicating the declaration of $fh. Move that out:
my $fh;
open $fh, '<', 'test1'
or open $fh, '<', 'test2'
or open $fh, '<', 'test3'
or die "Can't open whatever: $!";
If you enable warnings it will tell you "my" variable $fh masks earlier declaration in same statement
As an alternative, you can use foreach to loop over files,
my #files = map "dir$_/file.o$ARGV[0]", 1 ..3;
my $fh;
for (#files) {
open($fh, "<", $_) and last;
undef $fh;
}
$fh or die $!;
"Is there an elegant way to do this?"
The warning is because of multiple declarations of $fh, as has already been explained, but I would prefer to see the file selected separately, because
There may be more than one file with the desired ID
If the file is in dir1 or dir2 but the open fails for some other reason, your program will go on to try dir3 and wrongly report No such file or directory
I suggest something like this
use strict;
use warnings;
my ($id) = #ARGV;
my $filename = do {
my #files = grep -f, map "$_/file.o$id", qw/ dir1 dir2 dir3 /;
die #files . " matching files found" unless #files == 1;
$files[0];
};
open my $fh, '<', $filename or die qq{Couldn't open "$filename" for reading: $!};

How to Write a Variable to File in Perl

I have info contained in a variable that I need to have written to a file. My script needs to be create the file and then write to it.
Here's my current script:
my $file_location = '/network/$custom_directory/$custom_filename';
open(my $file ">", $file_location) or die $!;
print $file "$variable_data";
close $file;
I'm getting the feeling that my script is getting hung up on the actual file creation, rather than the variable-writing process.
The error I get when I run the script is: 'No such file or directory' at the line where I try to open the file.
You have a syntax error in your programme. All three arguments of open must be separated by commas.
open my $file, '>', $file_location or die $!;
Single quotes do not interpolate, unlike double quotes, so you probably need them in the file path:
my $file_location = "/network/$custom_directory/$custom_filename";
BTW: Including a sole variable into double quotes server no purpose for string contents. You can equivalently
print $file $variable_data;
You didn’t say what your error is.
But you’re missing a comma.
You also have the wrong quotes.
You also (probably) forgot the newline at the end.
And you forgot to check that the close succeeded lest your filesystem should have filled up.
You may have forgotten the binmode or the encoding.
Which gives you something like this, with obligatory preamble:
#!/usr/bin/perl
use strict;
use warnings;
my $custom_directory = "something old";
my $custom_filename = "something new";
my $data = "something borrowed";
my $path = "/network/$custom_directory/$custom_filename";
open(my $handle, ">", $path) || die "can't open $path: $!";
binmode($handle); # for raw; else set the encoding
print $handle "$data\n";
close($handle) || die "can't close $path: $!";
Two things: First the file location is in single-quotes, so the $ variables won't be interpolated. Second, you're missing a comma in the call to open. The code should read:
my $file_location = "/network/$custom_directory/$custom_filename";
open(my $file, ">", $file_location) or die $!;
First,
use strict;
use warnings;
may help. Second, variable interpolation requires double quoted strings:
my $file_location = "/network/$custom_directory/$custom_filename";
Third, you may probably need a \n at the print statement:
print $file "$variable_data\n";
And finally, your open statement should be:
open my $file, ">", $file_location or die $!;

How to refer to perl arguments when looping through them?

Hi I'm trying to use the code written in this answer https://stackoverflow.com/a/1712480/1740992 :
foreach (#ARGV){
print "file: $_\n";
# open your file here...
#..do something
# close your file
}
I don't know how to refer to the argument. When my scipt was just running on one file I open it by running:
$kml = "adair.kml";
open INPUT, "<$kml";
what do I replace my filename with?
I've tried $ARGV[n]
thanks
You're already using it, it is $_.
You can use a named variable instead with:
foreach my $foo (#ARGV){
for my $arg (#ARGV) {
open my $fh, '<', $arg or die "Cannot open '$arg': $!";
# ...
close $fh;
}
Your code block:
$kml = "adair.kml";
open INPUT, "<$kml";
should be replaced with:
use strict;
use warnings;
my $kml = $ARGV[0];
open my $input_fh, '<', $kml or die "Couldn't open $kml $!";
if your code is only going to run with one argument.