Archive::Tar : can't read tar created just before in Perl - perl

I'm trying to read the content of a file (a.txt) that I just created. This file contains a string consisting of "ABCDE", which I then tar with the write() function. I can see that the "a.tar" is created in my directory, but when I come up to the read() function, I get an error : Can't read a.tar : at testtar.pl line 14.
Am I doing something wrong ? Is it because I am on Windows ?
use strict;
use warnings;
use Archive::Tar;
# $Archive::Tar::DO_NOT_USE_PREFIX = 1;
my $tari = Archive::Tar->new();
$tari->add_files("a.txt");
$tari->write("a.tar");
my $file = "a.tar";
my $tar = Archive::Tar->new() or die "Can't create a tar object : $!";
if(my $error = $tar->read($file)) {
die "Can't read $file : $!";
}
my #files = $tar->get_files();
for my $file_obj(#files) {
my $fh = $file_obj->get_content();
binmode($fh);
my $fileName = $file_obj->full_path();
my $date = $file_obj->mtime();
print $fh;
}
Thanks.

You misunderstand the return value of read of Archive::Tar:
$tar->read ( $filename|$handle, [$compressed, {opt => 'val'}] )
Returns the number of files read in scalar context, and a list of Archive::Tar::File objects in list context.
Please change the following
if(my $error = $tar->read($file)) {
die "Can't read $file : $!";
}
to
unless ($tar->read($file)) {
die "Can't read $file : $!";
}
and try again.

This is wrong:
my $fh = $file_obj->get_content();
binmode($fh);
get_content() gives you the contents of the file and not a filehandle. binmode() is expecting a filehandle. Also, you can use !defined instead of unless (I think it's easier to read).
Rewritten below:
#!/bin/env perl
use strict;
use warnings;
use Archive::Tar;
my $tari = Archive::Tar->new();
$tari->add_files("a.txt");
$tari->add_files("b.txt");
$tari->add_files("c.txt");
$tari->add_files("d.txt");
$tari->write("a.tar");
my $file = "a.tar";
my $tar = Archive::Tar->new() or die "Can't create a tar object : $!";
if(!defined($tar->read($file)))
{
die "Can't read $file : $!";
}
my #files = $tar->get_files();
for my $file_obj(#files)
{
my $fileContents = $file_obj->get_content();
my $fileName = $file_obj->full_path();
my $date = $file_obj->mtime();
print "Filename: $fileName Datestamp: $date\n";
print "File contents: $fileContents";
print "-------------------\n";
}

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.

readdir() attempted on invalid dirhandle

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.

Perl script not writing to extracted zip file

I'm writing a perl script to extract a specifically named file from a zip file and write to that extracted file (there's more than that to the script but this is the part that I'm getting stuck on). The code below is a portion of the perl script.
I cannot figure out why it's not writing to the file!
my $zipName = "f:\\data\\archive.zip";
my $destPath = "f:\\data\\dataFile.DAT";
my $tempZip = Archive::Zip->new();
my $dataNum = " 0 0";
unless ($tempZip->read($zipName) == AZ_OK )
{
die 'read error';
}
my #dataFileMatches = $tempZip->membersMatching( 'dataFile.*\.DAT' );
my $dataFile;
if($#dataFileMatches> -1)
{
$dataFile = $dataFileMatches[0];
my $fileContents = $tempZip->contents($dataFile);
my $newContents = substr $fileContents, 0, 10;
$newContents = $newContents.$dataNum;
my $dataFilename = $dataFile ->fileName();
open(my $fh, '>', $dataFilename) or die "Could not open file '$dataFilename' $!";
$tempZip->contents($dataFile, $newContents);
$fileContents = $tempZip->contents($dataFile);
print "New FileContents - $fileContents\n";
#print $fh $newContents;
#copy($fh, $destPath);
close $fh;
}
Here is the code that is not being executed:
use strict;
use warnings;
use File::Copy qw(copy);
use Archive::Zip qw/ :ERROR_CODES :CONSTANTS /;
my $filename = 'dataFile.DAT';
open(my $fh, '>', $filename) or die "Could not open file";
print $fh "test\n";
close $fh;
But if I create a dummy TEXT file in the exact same directory that this extracted DAT file is in, it works.
You have to use the extractMemberWithoutPaths() method of Archive::Zip.
Here is how to extract a file:
#!perl
use strict;
use warnings;
use Data::Dumper qw/Dumper/;
use FindBin qw/$Bin/;
use File::Spec;
use Archive::Zip qw/AZ_OK/;
my $zipName = File::Spec->catfile($Bin, '/archive.zip');
my $destPath = File::Spec->catfile($Bin, 'dataFile.DAT');
my $tempZip = Archive::Zip->new();
my $dataNum = " 0 0";
unlink $destPath if -e $destPath;
unless ($tempZip->read($zipName) == AZ_OK ) {
die 'read error';
}
my #dataFileMatches = $tempZip->membersMatching( {regex => 'dataFile.*\.DAT'} );
$tempZip->extractMemberWithoutPaths($dataFileMatches[0]); # extract $fileContents to current working directory
if ( -e $destPath ) {
print "file was extracted\n";
}else{
print "File was not extracted :(\n";
}

How to read file in Perl and if it doesn't exist create it?

In Perl, I know this method :
open( my $in, "<", "inputs.txt" );
reads a file but it only does so if the file exists.
Doing the other way, the one with the +:
open( my $in, "+>", "inputs.txt" );
writes a file/truncates if it exists so I don't get the chance to read the file and store it in the program.
How do I read files in Perl considering if the file exists or not?
Okay, I've edited my code but still the file isn't being read. The problem is it doesn't enter the loop. Anything mischievous with my code?
open( my $in, "+>>", "inputs.txt" ) or die "Can't open inputs.txt : $!\n";
while (<$in>) {
print "Here!";
my #subjects = ();
my %information = ();
$information{"name"} = $_;
$information{"studNum"} = <$in>;
$information{"cNum"} = <$in>;
$information{"emailAdd"} = <$in>;
$information{"gwa"} = <$in>;
$information{"subjNum"} = <$in>;
for ( $i = 0; $i < $information{"subjNum"}; $i++ ) {
my %subject = ();
$subject{"courseNum"} = <$in>;
$subject{"courseUnt"} = <$in>;
$subject{"courseGrd"} = <$in>;
push #subjects, \%subject;
}
$information{"subj"} = \#subjects;
push #students, \%information;
}
print "FILE LOADED.\n";
close $in or die "Can't close inputs.txt : $!\n";
Use the proper test file operator:
use strict;
use warnings;
use autodie;
my $filename = 'inputs.txt';
unless(-e $filename) {
#Create the file if it doesn't exist
open my $fc, ">", $filename;
close $fc;
}
# Work with the file
open my $fh, "<", $filename;
while( my $line = <$fh> ) {
#...
}
close $fh;
But if the file is new (without contents), the while loop won't be processed. It's easier to read the file only if the test is fine:
if(-e $filename) {
# Work with the file
open my $fh, "<", $filename;
while( my $line = <$fh> ) {
#...
}
close $fh;
}
You can use +>> for read/append, creates the file if it doesn't exist but doesn't truncate it:
open(my $in,"+>>","inputs.txt");
First check whether the file exists or not. Check the sample code below :
#!/usr/bin/perl
use strict;
use warnings;
my $InputFile = $ARGV[0];
if ( -e $InputFile ) {
print "File Exists!";
open FH, "<$InputFile";
my #Content = <FH>;
open OUT, ">outfile.txt";
print OUT #Content;
close(FH);
close(OUT);
} else {
print "File Do not exists!! Create a new file";
open OUT, ">$InputFile";
print OUT "Hello World";
close(OUT);
}

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";