Perl - Argument unable to detect in Directory name - perl

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.

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"

Asking for other inputs after piping a file to a perl script from a shell script

I am working on a school project that involves having a main shell script that will prompt the user for a text file that contains 50 words. If the shell script finds that file in the same directory as the shell and perl scripts, it will then print a menu asking if the user wants to sort the list using shell and outputting the sorted list to a new file (that one is finished and works), make a call to a perl script, where the perl script will take that file and print all the words in that file, then prompt the user for what word they want to search for. This will return what line the word is on in the list. What I have done is if the user selects to sort using the perl script, we pipe the inputted file in shell to the perl script with:
cat $filename | ./search.pl
Which happens to successfully pipe the file over to the perl script where we can use it. The first while loop is where we access the list and print every word/line for the user to see, which works fine. But this is where I run into trouble. After the whole list is printed, the printf line where it asks for the word they want to search for will print, but then the program will just stop without allowing anymore input, and go back to the terminal. What my logic for this search script is that we print every word for the user to see what they can search for, and then ask them what they want to search for, and then look through the inputted file from the shell script with a while loop; if we find it, print that we found it on that line, if we don't find it then go the to the next line, and if we hit the end without finding it just print that it can't be found.
Why am I unable to enter more input with the call to STDIN and assign it to $word to use in the second while loop? Also, when I am doing the second while loop, is using <> by itself after asking for a different output going to mess things up? If so, how do I make a reference again to the file for the second while loop?
#!/usr/bin/env perl
$count = 1; #global variable for return value
# of words.
while (<>) {
printf "$_";
}
#Now that we have opened the file, printed off everything for the user to see, they can now enter a word in a prompt to
# see what line it is on.
printf "\nPlease enter the word you want to search for\n";
my $word = <STDIN>;
chomp $word;
while ( $line = <> ) {
if ( $line =~ m/$word/ ) {
print "$word has been found on line $count.\n\n";
} elsif ( $line !=~ m/$word/ ) {
$count++;
} else {
print "$word cannot be found.";
}
}
The Shell script (for reference):
#!/bin/bash
clear
printf "Hello. \nPlease input a filename for a file containing a list of words you would like to use. Please allow for one word per line.\n -> "
read filename
printf "You have entered the filename: $filename.\n"
if [ -f "$filename" ] #check if the file even exists in the current directory to use
then
printf "The file $filename exists. What would you like to do with this file?\n\n"
else
printf "The file: $filename, does not exist. Rerun this shell script and please enter a valid file with it's proper file extension. An example of this would be mywords.txt \n\nNow exiting.\n\n"
exit
fi
printf "Main Menu\n"
printf "=========\n"
printf "Select 1 to sort file using Shell and output to a new file.\n"
printf "Select 2 to sort file using Perl and output to a new file.\n"
printf "Select 3 to search for a word using Perl.\n"
printf "Select 4 to exit.\n\n"
echo "Please enter your selection below"
read selection
printf "You have selected option $selection.\n"
if [ $selection -eq "1" ]
then
read -p "What would you like to call the new file? " newfile #asks user what they want to call the new file that will have the sorted list outputted to it
sort $filename > $newfile
echo "Your file: $newfile, has been created."
fi
if [ $selection -eq "2" ]
then
read -p "What would you like to call the new file? " newfile2
cat $filename | ./sort.pl
# > $newfile2 #put the sorted list into the new output file that the user specificed with newfile2
fi
if [ $selection -eq "3" ]
then
cat $filename | ./search.pl
fi
if [ $selection -eq "4" ]
then
printf "Now exiting.\n\n"
exit
fi
I have modified your code as shown below. For your understanding, i have been putting comments but try to avoid comments wherever not required.
Code:
#!/usr/bin/env perl
use strict;
use warnings;
#Input File passing as an argument to the program
my $InFile = $ARGV[0];
#Opening and reading a file using filehandle $fh
open my $fh,'<', $InFile or die "Couldn't open the file $InFile : $!";
while (<$fh>) {
printf "$_";
}
# Seek function as shown below will reset the file handle position to beginning of the file
seek($fh, 0, 0);
printf "\nPlease enter the word you want to search for\n";
my $word = <STDIN>;
chomp $word;
my $count = 1; #global variable for return value of words
my $val = 0;
while (my $line = <$fh>) {
if ($line =~ m/$word/) {
print "$word has been found on line $count.\n\n";
$val++;
}
elsif ($line !~ m/$word/) {
$count++;
}
}
if ($val == 0) {
print "$word cannot be found";
}
close($fh);

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

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?

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;

This is a Perl script to grep a pattern entered from docx files. Please anybody, please point out my mistakes to make it work?

#!usr/bin/perl
#script: patternsearch.pl : Program to search for specific pattern inside the file.
print ("Prgramme name: $0 \n");
print ("Enter pattern: \n");
chop ($pattern = <STDIN>);
print ("Enter the absolute folder path: \n");
chop ($folder = <STDIN>);
print ("Enter file type: \n");
chop ($filetype = <STDIN>);
die ("pattern not entered??? \n") if ($pattern eq " ");
if ($filetype eq "txt") {
foreach $search (`find $folder -type f -name "*.$filetype"`) {
do `grep -H $pattern $search>> patternsearch.txt`;
}
}
else {
foreach $search (`find $folder -type f -name "*.$filetype"`) {
do `antiword $search | grep -H $pattern >> patternsearch.txt`;
}
}
print ("Taskcompleted \n");
*.docx files are not plain text or even actually XML -- they're zipped bundles of XML and other stuff. You can't grep for text in the zipped file. You could unzip a *.docx, and then grep in the contents -- although in my experience the XML is written without line breaks, such that each grep hit would be the entire contents of the document.
You really should
use strict;
use warnings;
at the start of every program, and declare all you variables with my at the point of first use. This applies especially if you are asking for help with your program, and will quickly draw attention to a lot of simple mistakes.
You ought to use chomp instead of chop, as the latter just removes the last character from a string whereas the former checks to see if it is a line terminator (newline) before it removes it.
The only problems I can find is that you don't chomp the output from your backtick find commands: you should write chomp $search before the grep or antiword commands. Also (to paraphrase Yoda) there is no do before a backticks command. Remove that from before grep and antiword and your program may work.
If you have any further problems, please explain what output you expect, and what you are getting.