Downloading sequence file with perl - perl

I am trying to download the sequence file from the gene bank database using perl but it shows error. I don't have any guide to correct my program.
Can any one help me with this? The error is in line 6 (use Bio::DB::GenBank;)
File accnumber.txt is on my desktop and I am running the program from desktop itself. I am using CentOS.
#!usr/bin/perl -w
use strict;
use warnings;
use Bio::DB::GenBank;
open (INPUT_FILE, 'accnumber.txt');
open (OUTPUT_FILE, 'sequence_dwnl.fa');
while()
{
chomp;
my $line = $_;
my #acc_no = split(",", $line);
my $counter = 0;
while ($acc_no[$counter])
{
$acc_no[$counter] =~ s/\s//g;
if ($acc_no[$counter] =~ /^$/)
{
exit;
}
my $db_obj = Bio::DB::GenBank->new;
my $seq_obj = $db_obj->get_Seq_by_acc($acc_no[$counter]);
my $sequence1 = $seq_obj->seq;
print OUTPUT_FILE ">"."$acc_no[$counter]","\n";
print OUTPUT_FILE $sequence1,"\n";
print "Sequence Downloaded:", "\t", $acc_no[$counter], "\n";
$counter++;
}
}
close OUTPUT_FILE;
close INPUT_FILE;
These are errors I get:
Bareword "Bio::DB::GenBank" not allowed while "strict subs" in use at db.pl line 6.
Bareword "new" not allowed while "strict subs" in use at db.pl line 27.
Bareword "seq" not allowed while "strict subs" in use at db.pl line 29.
Execution of db.pl aborted due to compilation errors.

Since line you mention loads external Perl module Bio::DB::GenBank from CPAN, first thing that came to my mind: Is the module installed on your system?
Try running command cpan Bio::DB::GenBank as root (e.g. by prepending it with sudo). This should not hurt even if the module is installed, in that case it will check CPAN for updates.

In addition to the above answer,
Please use die function to check whether the files are opened.
open (INPUT_FILE, 'accnumber.txt');
open (OUTPUT_FILE, 'sequence_dwnl.fa');
Like this:
open (my $input_file, '<', 'accnumber.txt') or die "Could not open because $!\n";
open (my $output_file, '<', 'sequence_dwnl.fa') or die "Could not open because $!\n";
Also, please specify the purpose of opening each file with these operators:
< to open file in read only mode.
> to overwrite the file content.
>> to append the file content.
Also please check whether you have Bio::DB::GenBank module installed or not.
You can do that by running this in command line:
perldoc -l Bio::DB::GenBank or perl -MBio::DB::GenBank -e 1

Related

Perl webscript doubtful security

Recently with a project I inherited a simple perl script that generates a PDF of the page:
#!/usr/bin/perl
use CGI;
my $file="showdata.pdf";
my $filepath= "/tmp/$file";
system("wkhtmltopdf \"sample.com/showdata.php?".$ENV{"QUERY_STRING"}."\" $filepath");
print ("Content-Type:application/x-download\n");
print ("Content-Disposition: attachment; filename=$file\n\n");
open FILE, "< $filepath" or die "can't open : $!";
binmode FILE;
local $/ = \10240;
while (<FILE>){
print $_;
}
close FILE;
unlink ($filepath);
I am concerned direct substitution variable $ENV{"QUERY_STRING"}. However, in a cursory testing, I did not reveal any problems. I was not able to create/delete files in a known writable directory. I tried not well or problems in the script should not be?
Yes, that's insecure. What if QUERY_STRING was "; rm -fr /;?
Then your system call would be:
wkhtmltopdf "sample.com/showdata.php?"; rm -fr /; /tmp/showdata.pdf
Accessing $ENV{"QUERY_STRING"} directly is insecure. In my case, my digital parameter 'o' must be forced to be integer. There is secure script version:
#!/usr/bin/perl
use CGI;
my $query = new CGI;
my $o = int($query->param('o'));
my $file="showdata.pdf";
my $filepath= "/tmp/$file";
system("wkhtmltopdf \"sample.com/showdata.php?o=".$o."\" $filepath");
print ("Content-Type:application/x-download\n");
print ("Content-Disposition: attachment; filename=$file\n\n");
open FILE, "< $filepath" or die "can't open : $!";
binmode FILE;
local $/ = \10240;
while (<FILE>){
print $_;
}
close FILE;
unlink ($filepath);
If you concern about security, run your Perl script with taint option -T.
For example, the following script will halt your script with warning: Insecure $ENV{PATH} while running with -T switch at ./foo.pl line 4.
#!/usr/bin/perl -T
my $foo = $ENV{FOO};
system("ls -l $foo");
Note: option -t can be used instead of -T if you just need warning.

Error while trying to rename files in script and cmd line

$dir = "/home/naveen/mp3tag/testfolder";
opendir(DMP3, $dir) || die("Cannot open directory");
#files= readdir(DMP3;
foreach $f (#files)
{
unless ( ($f eq ".") || ($f eq "..") )
{
$oldfile = $f;
$newfile = $f;
$newfile =~ s/ /_/g;
print "Old file: $oldfile \t";
print "New file: $newfile";
print "\n";
rename ("$oldfile", "$newfile") or warn "Couldn't rename $oldfile to $newfile !\n";
}
}
I'm writing a simple program to add underscores to an existing file and rename it. This is how far ive gotten with the code. However its not able to rename the file and gives me a warning and i'm not sure where the mistake is.
Also when i tried the same line on the cmd line I get the following error msg.
$ rename Jacques\ Greene\ -\ Clark\ \(Original\ Mix\).mp3 JG - C.mp3
Bareword "mp3" not allowed while "strict subs" in use at (eval 1) line 1.
$ rename Jacques\ Greene\ -\ Clark\ \(Original\ Mix\) JG - C
Can't locate object method "Original" via package "Mix" (perhaps you forgot to load "Mix"?) at (eval 1) line 1.
You're trying to rename all the files in the directory, not just one file. The error could be a great many things, since you did not mention it, I could only guess.
rename is, as I recall, a bit wonky, and using move from File::Copy is a safer bet. Also, you might want to avoid renaming directories. Using a more intuitive interface would probably not be a bad idea either.
One of your biggest mistakes is not using use strict; use warnings;. The amount of trouble you bring on yourself by leaving these out cannot be underestimated.
use strict;
use warnings;
use File::Copy qw(move);
for (#ARGV) {
my $org = $_;
tr/ /_/;
move($org, $_) or warn "Couldn't move $org to $_: $!";
}
Usage:
perl script.pl /home/naveen/mp3tag/testfolder/*.mp3
So, as long as you give a proper glob as argument, your script will only affect those files. You can add more checks to make it stricter.
If that commandline attempt of yours is meant to be with using the tool from /usr/bin/rename, I would hazard a guess that your error can simply be avoided by using quotes.
This working example might help
use strict;
use warnings;
use File::Copy;
my $dir = '/home/naveen/mp3tag/testfolder';
my #mp3s = glob ("$dir/*.mp3");
for my $mp3 (#mp3s) {
my $new_mp3 = $mp3;
$new_mp3 =~ s/\s/_/g;
move($mp3, $new_mp3);
}
You are calling rename in /usr/bin. If you want to call your program, choose a better name for it, or call it with full path specified.
But before you do, add at least the missing right bracket to readdir.

filehandle - won't write to a file

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.

How can I redirect output of die function to a file in Perl?

I want to redirect the die messages to a separate file so that I can compare that file later to determine what went wrong.
But this code gives me errors:
$ cat test.pl
use strict;
use warnings;
my $log = "msglog.log";
die $log "DEAD$!";
$ perl test.pl
Missing comma after first argument to die function at test.pl line 5, near ""DEAD$!";"
Execution of test.pl aborted due to compilation errors.
$
I do not want to do a 2> from the caller. Is there someway to redirect them from within the script?
You can install a $SIG{__DIE__} handler to be run just before the "die" runs. The handler will be called with the error message which you can log:
local $SIG{__DIE__} = sub {
my ($message) = #_;
# log the message
};
See $SIG{expr} in perlvar for details.
Perl's die prints to STDERR so you could redirect STDERR to a file.
#!/usr/bin/env perl
# the path above depends on your system
open(STDERR, ">>", "errlog.log");
die "Hello";
The Log::Log4perl module offers more than a few options.
One can choose to output the error message to both STDERR and the logfile.
my $logger = Log::Log4perl->init ( 'log.conf' );
# Configuration file controls what to output, like time, line number, class...
$logger->get_logger ( 'Hello::World' ); # Define which class logger to use
.
.
.
open my $fh, '<', $file
or $logger->logdie ( "Log the demise: $!" ); # ... and die;
While it requires a little bit more effort in terms of setup, its flexibility unlocks a great deal of potential.

Why does perl complain about "Too many arguments for open" when I run it in a shell script?

I run my Perl script (gettotal.pl) and it works fine. I managed to get the sum of TOTAL.txt and append the output value to test.txt. But when I run it inside shell script (test.sh) I got this error:
Too many arguments for open at /home/daily/scripts/per_NODE_HR/gettotal.pl line 29, near ""$dir")"
Execution of /home/daily/scripts/per_NODE_HR/gettotal.pl aborted due to compilation errors.
What is the difference between running it manually (./gettotal.pl) and running it inside shell script? Simple yet still confusing for me:-)
gettotal.pl
#!/opt/perl/bin/perl-w
use strict;
my $sum;
open(FH,"/home/daily/scripts/per_NODE_HR/date.txt");
chomp (my #date = <FH>);
my $path = "/home/daily/output/per_NODE_HR/$date[0]/TOTAL.txt";
open(FILE,"$path") or die "Unable to open $path: $!";
my #hits = <FILE>;
$sum=sum($#hits);
print "TOTAL = $sum";
print "\n";
sub sum {
if ($_[0] == 0) {
return $hits[0];
}
return $hits[$_[0]] + sum($_[0]-1);
}
my $dir = "/home/daily/output/per_NODE_HR/$date[0]/test.txt";
open(OUT,'>>', "$dir") or die "Cannot open $dir: $!";
print OUT "TOTAL: $sum";
close OUT;
close FILE;
close FH;
shell script
#!/bin/sh
perl /home/daily/scripts/per_NODE_HR/gettotal.pl
The error you're getting suggests that your system perl is a truly ancient version... The three-argument form of open was added in perl 5.6.0 (released March 22, 2000), so a complaint about your open having too many arguments would seem to indicate that you're passing your code to a 5.5.x or older perl. Try perl -v on the command line to see what version the system perl is.
As for how to resolve this, call it in your shell script with just /home/daily/scripts/per_NODE_HR/gettotal.pl instead of perl /home/daily/scripts/per_NODE_HR/gettotal.pl and it will get passed to /opt/perl/bin/perl-w as specified in the shebang (#!) line, just like it does when you run it manually with ./gettotal.pl.
Incidentally, you might also want to add a use warnings along with use strict instead of relying on your code being run with perl -w. If you use perl gettotal.pl, warnings will not be enabled.
Almost certainly, perl != /opt/perl/bin/perl.
Try which perl.