readdir() attempted on invalid dirhandle - perl

What am I doing wrong? I've tried many things but can't seem to read from this file. Thanks!
my $d = 'URLs.txt';
open(my $fh, '<:encoding(UTF-8)', $d)
#opendir(D, "$d") || die "Can't open directory $d: $!\n";
or die "Can't open directory $d: $!\n";
my #list = readdir($fh);
closedir($fh);
foreach my $f (#list) {
my $json_data = get "$f";
my $json_obj = new JSON;
my $URLdata = $json_obj->decode($json_data);
return $URLdata->{'status'} eq 'UP';
}

URLs.txt appears to be a file, not a directory
To open a file, write
open my $fh, '<', $filename or die $!;
and read from it with
while ( my $line = <$fh> ) { ... }
To open a directory, write
opendir my $dh, $dirname or die $!;
and read its contents with
while ( my $item = readdir $dh ) { ... }
If you had use strict and use warnings 'all' in place as you should in every Perl program you write you would have seen
readdir() attempted on invalid dirhandle $fh
closedir() attempted on invalid dirhandle $fh
which would have guided you towards the problem
You may be better of with other functions, depending on what it is you want to do

Your variable names are not great, to put it mildly. Let's fix that!
use strict;
use warnings;
use JSON;
use LWP::Simple;
my $file = 'URLs.txt';
open(my $fh, '<:encoding(UTF-8)', $file) or die "Can't open file $file: $!\n";
chomp(my #lines = <$fh>);
close($fh);
foreach my $url (#lines) {
my $json_text = get($url);
if (defined($json_text)) {
my $perl_ref = decode_json($json_text);
if ($perl_ref->{status} eq 'UP') {
print "foo\n";
}
} else {
# handle the error!
}
}
You'll notice I also:
Added use strict and use warnings, which should be in every Perl file you write
Added error-checking to the LWP get() result
Removed indirect object notation (new JSON) in favor of the decode_json() convenience function. It's the same as JSON->new->utf8->decode(), only shorter.
Removed the return statement, because it doesn't make any sense outside of a subroutine. If this code has actually been yanked from a subroutine, then you should show that as part of your MCVE.

Related

Perl script returning 0 when a file is read

Im just trying to copy a file to a different directory before I process it. Here is the code:
use File::stat;
use File::Copy;
use LWP::UserAgent;
use strict;
use warnings;
use Data::Dumper;
use Cwd qw(getcwd);
my $dir = "\\folder\\music";
my $dir1 = "c:\\temp";
opendir(my $dh, $dir) or die "Cant open directory : $!\n";
#my #list = readdir($dh)
my #files = map { [ stat "$dir/$_", $_ ] }
grep( /Shakira.*.mp3$/, readdir( $dh ) );
closedir($dh);
sub rev_by_date
{
$b->[0]->ctime <=> $a->[0]->ctime
}
my #sorted_files = sort rev_by_date #files;
my #newest = #{$sorted_files[0]};
my $name = pop(#newest);
print "Name: $name\n";
#**********************
#Upto here is working fine
my $new;
open OLD,"<",$name or die "cannot open $old: $!";
from here the problem starts
open(NEW, "> $new") or die "can't open $new: $!";
while ()
{
print NEW $_ or die "can't write $new: $!";
}
close(OLD) or die "can't close $old: $!";
close(NEW) or die "can't close $new: $!";
The error im getting is :
cannot open Shakira - Try Everything (Official Video).mp3: No such file or directory at copy.pl line 49.
when Im chomping the filename, like
my $oldfile = chomp($name);
then the error is :
Name: Shakira - Try Everything (Official Video).mp3
old file is 0
cannot open 0: No such file or directory at copy.pl line 49.
Any idea?
chomp changes its argument in place and returns the number of removed characters. So the correct usage is
chomp(my $oldfile = $name);
Also, you probably wanted
while (<OLD>) {
instead of
while () {
which just loops infinitely.
Moreover, you correctly prepend $dir/ to a filename in the stat call, but you shold do so everywhere.

Can't use an undefined value as a symbol reference on line 12

So I am trying to teach myself perl as a new language. I find the best way to learn a new language is to set myself a project. This project is a text game. I have just started this evening. I need to take input from the user and then write it to a file. As I am going to be doing this over and over again, I thought it would be best to put the code in subroutines, as you can see below.
The only problem is that I keep getting the following error:
Can't use an undefined value as a symbol reference at book1.pl line 12, <> line 2.
Any help would be greatly appreciated :)
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
my $filename = 'save.txt';
sub open_save{
open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
}
sub close_save{
close my $fh;
}
print "Welcome to the 40K universe\nWhat is your first name?";
my $first_name = <>;
print"What is your surname?";
my $surname = <>;
my $name = $first_name . $surname;
open_save();
print "$name";
close_save();
my creates and returns a new variable. You pass this new variable to close, which quite legitimately complains that it's not a file handle.
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
sub open_save {
my ($filename) = #_;
open(my $fh, '>', $filename)
or die "Can't open file '$filename': $!\n";
return $fh;
}
sub close_save {
my ($fh) = #_;
close $fh;
}
{
my $filename = 'save.txt';
...
my $fh = open_save($filename);
print $fh "$name\n";
close_save($fh);
}

Perl Open: No such file or directory

I'm trying to read every text file in a directory into a variable then print the first 100 characters, including line breaks. However, Perl says that the files don't exist even though they really do exist.
use strict;
use warnings;
my $dir = "C:\\SomeFiles";
my #flist;
open(my $fh, "dir /a:-d /b $dir |") || die "$!";
while (<$fh>) {
if ($_ =~ /.*(.txt)$/i) {
push(#flist, $_);
}
}
foreach my $f (#flist) {
print "$dir\\$f";
my $txt = do {
local $/ = undef;
open(my $ff, "<", "$dir\\$f") || die "$!";
<$ff>;
};
print substr($txt, 0, 100);
}
When I run the script, the following is written to the console:
C:\SomeFiles\file1.txt
No such file or directory at script.pl line 19, <$fh> chunk 10.
It's looking at the right file and I'm certain that the file exists. When I try using this method to open a single file rather than getting each file via an array with foreach, it works just fine. Is there something obvious that I've overlooked here?
A better solution is to use readdir() instead (or File::Find if you ever want to do it recursively):
my $dir = "C:\\SomeFiles";
opendir(my $dh, $dir) || die "$!";
while (my $file = readdir($dh)) {
if ($file =~ /\\.txt$/i) {
print $file . "\n";
my $txt = do {
local $/ = undef;
open(my $ff, "<", "$dir\\$file") || die "$!";
<$ff>;
};
print substr($txt, 0, 100) . "\n";
}
}
closedir($dh);

Not getting any output while reading the file

I am trying to read the file from some other directory, it for me every things looks good but unfortunately neither i am getting any error nor any output.
I am working on windows Pc.
Here is My code:
use strict;
use warnings;
use Cwd;
#chdir('C:\\APTscripts\\APStress\\Logs');
chdir('C:\\Mahi_doc\\Apstress_logs');
my ($dir_01,$dir_02);
my #FILES;
$dir_01 = getcwd;
#print "$dir\n";
opendir(DIR_01, $dir_01) ;
#FILES=readdir(DIR_01);
close(DIR_01);
my $count=12;
my $lines;
for my $dir_02 (#FILES)
{
#print"$dir_02\n";
if ( -d $dir_02)
{
opendir (DIR_02, "$dir_01"."/"."$dir_02") ;
while(our $file = readdir(DIR_02))
{
if($file =~ /APStress.*UIlog/g)
{
# print"$file\n";
open(FH,$file) or die "can not open the file $!\n";
while (defined(my $lines = <FH>))
{
print"$lines\n";
if($lines=~ m/WATCHDOG/ || $lines=~ m/Excessive JNI/gi )
{#chks for watchdog/excessive jni issue exist
print "Got it\n";
}
elsif($lines=~ m/installd: eof/gi)
{
print "EOF:Got it \n";
}
}
}
}
}
}
In the open clause, give the full path for the file:
open(FH, "$dir_01/$dir_02/$file") or die "can not open the file $!\n";
and better use 3 arg open and lexical file handler:
open(my $FH, '<', "$dir_01/$dir_02/$file") or die "can not open the file $!\n";

Why do I get "can't use string as a SCALAR ref while strict refs" in Perl?

use strict;
my #array=('f1','f2','f3');
my $dir ='\tmp';
foreach (#array) {
my $FH = $_;
open ("$FH", ">$dir/${FH}.txt") or die $!;
}
foreach (#array) {
my $FH = $_;
close($FH);
}
i got "Can't use string ("f1") as a symbol ref while "strict refs" in use at bbb.pl line 6." error . What is the isuse ?
First: 2 arg open is bad, 3 arg open is better.
open( .. , ">", "$dir/${FN}.txt")
second, what on earth are you doing with open("$FH" ..
argument 1 to open is supposed to be an actual filehandle of sorts which can be connected to a datastream. passing it a string will not work.
INSANE: open( "Hello world", .... ) # how can we open hello world, its not a file handle
WORKS: open( *FH,.... ) # but don't do this, globs are package-globals and pesky
BEST: open( my $fh, .... ) # and they close themself when $fh goes out of scope!
third
foreach my $filename ( #ARRAY ){
}
Forth:
dir = \tmp ? are you sure? I think you meant /tmp , \tmp is something different altogether.
Fifth:
use warnings;
using strict is good, but you should use warnings too.
Sixth: Use names for variables that are explanatory, we know # is an array #array is not more helpful.
ALL TOGETHER
use strict;
use warnings;
my #filenames=('f1','f2','f3');
my #filehandles = ();
my $dir ='/tmp';
foreach my $filename (#filenames) {
open (my $fh,'>', "${dir}/${filename}.txt") or die $!;
push #filehandles, $fh;
}
# some code here, ie:
foreach my $filehandle ( #filehandles ) {
print {$filehandle} "Hello world!";
}
# and then were done, cleanup time
foreach my $filehandle ( #filehandles ){
close $filehandle or warn "Closing a filehandle didn't work, $!";
}
Alternatively, depending on what you were trying to do, this may have been better code:
use strict;
use warnings;
my #filenames=('f1','f2','f3');
my $dir ='/tmp';
foreach my $filename (#filenames) {
open (my $fh,'>', "${dir}/${filename}.txt") or die $!;
print {$fh} "Hello world!";
}
I don't explicitly close $fh, because its not needed, as soon as $fh goes out of scope ( at the end of the block in this case ) it is closed automatically.
You are using a string "f1" as the first argument to open which expects a filehandle.
You probably wanted to do:
my #filehandles = (); # Stash filehandles there so as to not lose filenames
foreach (#array) {
my $FH = $_;
open (my $fh, ">", "$dir/${FH}.txt") or die $!;
push #filehandles, $fh;
}