Please Help. Variable not being interpolated in Net :: SCP - perl

This code telnets to a remote machine, fetches a latest directory. Then the latest folder name is stored into a variable then scp from remote to local machine happens. But the scp part is not working.
#!/usr/bin/perl -w
use Net::Telnet;
use Net::SCP::Expect;
$telnet = new Net::Telnet ( Timeout=>10, Errmode=>'die');
$telnet->open('192.168.12.123');
$telnet->login("liam", "thegrey");
#output = $telnet->waitfor('/\$ $/i');
my #lines=$telnet->cmd('ls');
print"\t\tLOGIN IN SUCESS!!\n\n\n";
$telnet->cmd('cd vault');
print "\t\tThe latest file is >\n";
my #update;
#update=$telnet->cmd(
'ls -l| grep Latest| tail -5 | head -2 | tail -1|tr -s " " | cut -d " " -f9');
my $found=join("",#update);
print "$found"; #The required value is printed here.
my $scpe = Net::SCP::Expect->new(user=>'liam',password=>'thegrey');
#The $found variable is not being interpolated.
$scpe->scp("192.168.12.123:/root/vault/$found/latest/movie.mkv",
"/root/ashesh_assignment/movie.mkv");

That's not true. if $found contains the value xxx, then the string literal
"192.168.12.123:/root/vault/$found/latest/movie.mkv"
produces the string
192.168.12.123:/root/vault/xxx/latest/movie.mkv
Now, it wouldn't surprise me if $found contained a newline which would create an odd path. Maybe a chomp is in order?

Related

Why is there a 0 on a new line when I print in perl?

I'm trying to get the inode alone of a file that is passed through as an argument.
When I extract the inode, however, there is a 0 printed on a new line. I've tried to get rid of it with regex but I can't. I'm passing the script /usr/bin/vim The 0 isn't there when I run the command (ls -i /usr/bin/vim | awk '{print $1}'), but it is when I run my script.
How can I get rid of this 0?
my $filepath = $ARGV[0];
chomp $filepath;
$filepath =~ s/\s//g;
print ("FILEPATH: $filepath\n"); #looks good
my $inode = system("ls -i $filepath | awk '{print \$1}'");
$inode =~ s/[^a-zA-Z0-9]//g;
$inode =~ s/\s//g;
print ("$inode\n");
So my result is
137699967
0
When you invoke system you run the command provided as its argument, and that's what's outputting the inode number.
The return value of system is the exit code of the command run, which in this case is 0, and that's what your subsequent print call outputs.
To run an external program and capture its output, use the qx operator, like so:
my $inode = qx/ls -i $filepath | awk '{print \$1}'"/;
However, as Sobrique explained in their answer, you don't actually need to call an external program, you can use Perl's built-in stat function instead.
my $inode = stat($filepath)[1];
stat returns a list containing a variety of information about a file - index 1 holds its inode. This code won't handle if the file doesn't exist, of course.
Don't, just use the stat builtin instead
print (stat($filepath))[1]."\n";
print join "\n", map { (stat)[1] } #ARGV,"\n"

Perl - Argument unable to detect in Directory name

I was trying to get directory from Argument0 but the argument name was not show in directory when i print it out. Below is the script i am writing. I am using unix to run the perl program. Running Try.pl script file with command ./Try.pl Device1 .
The Output should be : /home/Folder/Master_File/Device1
As my argument0 was Device1.
But for now my output was /home/Folder/Master_File/$device
Can you help to advices what is going on with it. Thanks.
my $device;
$device = "$ARGV[0]";
print "$device\n"; # Device1
my $directory = '/home/Folder/Master_File/$device';
print "$directory\n"; # /home/Folder/Master_File/$device
print "$ARGV[0]\n"; # Device1
print "$device\n"; # Device1
'/home/Folder/Master_File/$device'
should be
"/home/Folder/Master_File/$device"
or
'/home/Folder/Master_File/' . $device
Single-quote don't interpolate.

unix functions inside perl

I tried to use some unix tools inside a perl driver script because I knew little about writing shell script. My purpose is to just combine a few simple unix commands together so I can run the script on 100 directories in one perl command.
The task is I have more than 100 folders, in each folder, there are n number of files. I want to do the same thing on each folder, which is to combine the files in them and sort the combined file and use bedtools to merge overlapping regions (quite common practice in bioinformatics)
Here is what I have:
#!/usr/bin/perl -w
use strict;
my $usage ="
This is a driver script to merge files in each folder into one combined file
";
die $usage unless #ARGV;
my ($in)=#ARGV;
open (IN,$in)|| die "cannot open $in";
my %hash;
my $final;
while(<IN>){
chomp;
my $tf = $_;
my #array =`ls $tf'/.'`;
my $tmp;
my $tmp2;
foreach my $i (#array){
$tmp = `cut -f 1-3 $tf'/'$i`;
$tmp2 = `cat $tmp`;
}
my $tmp3;
$tmp3=`sort -k1,1 -k2,2n $tmp2`;
$final = `bedtools merge -i $tmp3`;
}
print $final,"\n";
I know that this line isn't working at all..
$tmp2 = `cat $tmp`;
The issue is how to direct the output into another variable in perl and use that variable later on in another unix command...
Please let me know if you can point out where I can change to make it work. Greatly appreciated.
The output from backticks usually includes newlines, which usually have to be removed before using the output downstream. Add some chomp's to your code:
chomp( my #array =`ls $tf'/.'` );
my $tmp;
my $tmp2;
foreach my $i (#array){
chomp( $tmp = `cut -f 1-3 $tf'/'$i` );
chomp( $tmp2 = `cat $tmp` );
}
my $tmp3;
chomp( $tmp3=`sort -k1,1 -k2,2n $tmp2` );
$final = `bedtools merge -i $tmp3`;
To use a perl variable in the shell, this is an example :
#!/usr/bin/env perl
my $var = "/etc/passwd";
my $out = qx(file $var);
print "$out\n";
For the rest, it's very messy. You should take the time learning perl and not mixing coreutils commands and Perl, where perl itself is a better tool to do the whole joke.
OK. I gave it up on perl and decided to give it a try using shell script. It worked!!
Thanks for the above answers though!
for dir in `ls -d */`
do
name=$(basename $dir /)
cd $dir
for file in `ls`
do
cut -f 1-3 $file > $file.tmp
done
for x in `ls *tmp`
do
cat $x >> $name.tmp1
done
sort -k1,1 -k2,2n $name.tmp1 > $name.tmp2
bedtools merge -i $name.tmp2 > $name.combined
done

ssh login verification in perl

I am running following lines of code in perl script to find a df output of remote machines. this works fine and gather a info in #df_ret untill until ssh key is uptodate. if public is corrupted or changed, its not showing any sign of error in script. if i run manually then i will be asked for the password.
#df_ret = split /\n/, `ssh -q $server 'df -hP'`;
Is there any way i can verify that if ssh login is successful then this perl script line should be executed else not. been finding many searches on it but could not reach to the ONE. any help?
I have got one solution working as below;
#!/usr/local/bin/perl
my $line = `ssh $server -o 'BatchMode=yes' -o 'ConnectionAttempts=1' true`;
my $error = `echo $?`;
print "Error = $error";
if($error == 0 )
{
print "This is good";
#df_ret = split /\n/, `ssh -q $server 'df -hP'`;
}
else
{
print "This is bad";
}
Check the result of the ssh exec before splitting it:
$text = `ssh -q $server 'df -hP'` or die "unable to ssh\n";
#df_ret = split /\n/, $text;

How do I echo string with bash command more in Perl?

This is what I tried:
my $s = "s" x 1000;
my $r = `echo $s |more`;
But it doesn't work, my program exits directly...
It does not work in your example, because you never print $r. The output is captured in the variable $r. By using system() instead, you can see the output printed to STDOUT, but then you cannot use the output as you (probably) expected.
Just do:
print $r;
Update: I changed say to print, since "echo" already gives you a newline.
To escape shell meta characters, as mentioned in the comments, you can use quotemeta.
You should also be aware that | more has no effect when capturing output from the shell into a variable. The process is simply: echo | more | $r, and you might as well skip more.
try with the system() command :
my $s = "s" x 1000;
my $r = system("echo $s |more");
will display all your 's', and in $r you will have the result (0 in this case) of the command.