carnisitir
carnisitir

Reputation: 11

Use of uninitialized value $e2 in string eq & find: warning:

Hopefully you can help a scientist to decipher whats wrong with the code I'm trying to run to clean up some NGS results. The Perl file itself comes from https://github.com/mtokuyama/ERVmap, though I am posting the code below for reference. The other Perl files in the package work just fine and, while I have built a passing ability to use the linux terminal, Perl is a little beyond me.

The linux terminal I'm using is currently running: Ubuntu 16.04.6 LTS

This is the Perl code I'm trying to run using the following command line on linux as instructed by their GitHub page:

perl clean_htseq.pl ./ c c2 __
#!/usr/bin/env perl
#$Id: run_clean_htseq.pl,v 1.2 2015/03/02 17:24:35 yk336 Exp $

#
# create pbs file
#

use warnings;
use strict;
use File::Basename;
use POSIX;

my $dir = shift;
my $e1 = shift;
my $e2 = shift;
my $stop = shift;

die "$e1 eq $e2" if ($e1 eq $e2);



my $find = "find $dir -name \"*${e1}\"";
my $out = `$find`;


my @files = split(/\n/, $out);
for my $f (@files) {
    my $o = $f;
    $o =~ s/${e1}$/$e2/;
    my $cmd = "./clean_htseq.pl $stop $f > $o";
    print "$cmd\n";
    system($cmd);
}

The first error that I had was that the _clean_htseq.pl_ wasn't found (line 30, already altered to solution) which i solved by adding the ./ in front of it and giving the software permission to use the script file.

My current issue with the code/command line is the following error:

Use of uninitialized value $e2 in string eq at ./clean_htseq.pl line 18.
find: warning: Unix filenames usually don't contain slashes (though pathnames do).  That means that '-name ‘*./SRR7251667.c’' will probably evaluate to false all the time on this system.  You might find the '-wholename' test more useful, or perhaps '-samefile'.  Alternatively, if you are using GNU grep, you could use 'find ... -print0 | grep -FzZ ‘*./SRR7251667.c’'.

This has been tracked down to the "__" at the end of the command line, while i'm sure this is supposed to mean something to the script I removed it and resulted in the following error:

Use of uninitialized value $stop in concatenation (.) or string at clean_htseq.pl line 30.
./clean_htseq.pl  ./SRR7251667.c > ./SRR7251667.c2
Use of uninitialized value $e1 in string eq at ./clean_htseq.pl line 18.
Use of uninitialized value $e2 in string eq at ./clean_htseq.pl line 18.
Use of uninitialized value $e1 in concatenation (.) or string at ./clean_htseq.pl line 18.
Use of uninitialized value $e2 in concatenation (.) or string at ./clean_htseq.pl line 18.
 eq  at ./clean_htseq.pl line 18.

An error occurs too when I remove the "." from "./" but it comes back with an error about not finding the _clean_htseq.pl_ file which is in the working directory.

Upvotes: 0

Views: 483

Answers (1)

brian d foy
brian d foy

Reputation: 132783

Your problem seems to be here:

my $dir = shift;
my $e1 = shift;
my $e2 = shift;
my $stop = shift;

Outside of a subroutine, shift works on @ARGV—the array that holds the command line arguments. You shift four times, so you need four arguments:

perl clean_htseq.pl ./ c c2 __

You only seem to give it two, and $stop has no value (so you are giving it less than two):

./clean_htseq.pl $stop $f

You can't just remove arguments and hope things still work out. Likely you're going to have to look at the source to see what those things mean (which should motivate you as a scientist to use good variable names and document code—Best Practices for Scientific Computing).

A first step may be to set defaults. The defined-or operator does well here:

use v5.10;

my $dir  = shift // 'default_dir';
my $e1   = shift // 'default_value';
my $e2   = shift // 'default_value';
my $stop = shift // 'default_value';

Or, you could just give up if there aren't enough arguments. An array in scalar context gives you the number of elements in the array (although it doesn't guarantee anything about their values):

die "Need four arguments!\n" unless @ARGV == 4;

There are various other improvements which would help this script, some of which I go through in the "Secure Programming Techniques" chapter in Mastering Perl. Taking unchecked user input and passing it to another program is generally not a good idea.

Upvotes: 1

Related Questions