something wrong when I exec a script with perl (ubuntu10.10) - perl

I got a perl script named test_perl.pl and try to exec it.
The first line of the scrpit is:
#!/usr/bin/perl
When I try to exec this script, I get an error.
$ type perl
perl is /usr/bin/perl
$ ll /usr/bin/perl test_perl.pl
-rwxr-xr-x 2 root root 10352 2011-04-23 03:32 /usr/bin/perl*
-rwxr-xr-x 1 jim jim 12121 2013-11-21 11:47 test_perl.pl*
$ test_perl.pl
test_perl.pl: line 1: #!/usr/bin/perl: No such file or directory
I don't no why this happens.

You have a BOM (see http://en.wikipedia.org/wiki/Byte_order_mark) at the beginning of your file.
try
xxd test_perl.pl
to see it. Getting rid of the BOM will fix your script: Lots of ways to do this: Using awk to remove the Byte-order mark

Related

make_path does not set mode as specified

When I call make_path (from the core File::Path module, supplying a mode, the directory that is created does not have the mode I requested:
$ perl -MFile::Path=make_path -e 'make_path("foobar", { mode=>0770 });'
$ ls -ld foobar/
drwxr-x--- 2 itk itkadm 4096 Sep 19 11:10 foobar/
I was expecting to see:
drwxrwx--- 2 itk itkadm 4096 Sep 19 11:07 foobar/
Rather than setting the permissions for the directory to 0. Try instead just using the chmod option to File::Path::make_path
perl -MFile::Path=make_path -e 'make_path("foobar", { chmod=>0770 });'
I missed this detail in the make_path documentation:
mode: The numeric permissions mode to apply to each created directory
(defaults to 0777), to be modified by the current umask.
I was not expecting this because the shell equivalent (mkdir -m 0770 -p foobar) does not consider umask.
This works as expected:
$ perl -MFile::Path=make_path -e 'umask(0); make_path("foobar", { mode=>0770 });'
$ ls -ld foobar/
drwxrwx--- 2 itk itkadm 4096 Sep 19 11:13 foobar/
Note the umask(0).
As pointed out by Evan Carroll, the version of File::Path supplued with newer perl versions (>=5.24) have a chmod option which may be a more convenient way to set the mode of created directories.

Perl backticks: flags do not exist

When executing the following segment of code,
sub list {
my($self)=#_;
my $file = $self->{P_Dir}."/".$self->{Name};
print `ls –l $file`;
}
I get this error:
ls: cannot access –l: No such file or directory
I am not really sure what is causing that, since if I manually type ls -l into the command line, I do not see that error.
That – that you've thankfully copy & pasted is a Unicode en dash character (U+2013) and not the ASCII hyphen character - (U+002D).
Hmmm... It works for me though:
$ cat test.pl
#!/usr/bin/perl -w
use strict;
my $file = "rpm.pl";
print `ls -l $file`;
$ perl test.pl
-rw-r--r-- 1 dheeraj dheeraj 922 2012-10-22 19:56 rpm.pl

XML editing inside a Perl script

I am trying to us the perl -pi -e to edit the a line in a xml file. If I run the perl -pi -e command from the command line it works fine, but once I put in my script and use the system command I get the error listed below:
su: invalid option -- i
Try `su --help' for more information.
print "Please enter virtualhost 1 - Example - ucisha.com:";
my $virtualhost1 = <>;
system("ssh -t <HOST> \"sudo su - root -c perl -pi -e 's/xmlNamespaceAware=\"false\">/xmlNamespaceAware=\"false\"> <Alias>$virtualhost1<\/Alias>/g' /tcserver/springsource-tc-server-node/UCISjvm/conf/krh.xml\"");
You need to add quote marks around the argument you pass to -c.
At the moment you have -c perl and then -pi is taken as another argument to su not perl.

Can't find the process after invoking this Perl script in shell

t:
#!/usr/bin/perl
exec("perl -Ilib -d" . $ARGV[0]);
It's invoked as t perl_script.
But after that I can't find it by ps,and can't terminate it by ^C
What's wrong ?
http://perldoc.perl.org/functions/exec.html
You're exec'ing perl with the args and perl_script you pass in. This means the current script t ceases to exist and is replaced by perl -Ilib -dperl_script.
The process you're looking for with ps will be the one you passed in (perl_script)
Edit for comment from OP below:
The actual process is perl since that's what you exec'd, but you can certainly find it via the perl_script you passed in using grep:
$ ps -ef |grep perl_script
broach 13039 2264 0 01:08 pts/0 00:00:00 perl -Ilib -dperl_script
Do you need to include a space after -d? Otherwise you are exec'ing
perl -Ilib -dperl_script
instead of
perl -Ilib -d perl_script
Cleaner still:
exec("perl","-Ilib","-d",$ARGV[0]);
exec($^X, "-Ilib", "-d", $ARGV[0]);

help using command line to extract snippets of data on stdout

I would like the option of extracting the following string/data:
/work/foo/processed/25
/work/foo/processed/myproxy
/work/foo/processed/sample
=or=
25
myproxy
sample
But it would help if I see both.
From this output using cut or perl or anything else that would work:
Found 3 items
drwxr-xr-x - foo_hd foo_users 0 2011-03-16 18:46 /work/foo/processed/25
drwxr-xr-x - foo_hd foo_users 0 2011-04-05 07:10 /work/foo/processed/myproxy
drwxr-x--- - foo_hd testcont 0 2011-04-08 07:19 /work/foo/processed/sample
Doing a cut -d" " -f6 will get me foo_users, testcont. I tried increasing the field to higher values and I'm just not able to get what I want.
I'm not sure if cut is good for this or something like perl?
The base directories will remain static /work/foo/processed.
Also, I need the first line Found Xn items removed. Thanks.
You can do a substitution from beginning to the first occurrence of / , (non greedily)
$ your_command | ruby -ne 'print $_.sub(/.*?\/(.*)/,"/\\1") if /\//'
/work/foo/processed/25
/work/foo/processed/myproxy
/work/foo/processed/sample
Or you can find a unique separator (field delimiter) to split on. for example, the time portion is unique , so you can split on that and get the last element. (2nd element)
$ ruby -ne 'print $_.split(/\s+\d+:\d+\s+/)[-1] if /\//' file
/work/foo/processed/25
/work/foo/processed/myproxy
/work/foo/processed/sample
With awk,
$ awk -F"[0-9][0-9]:[0-9][0-9]" '/\//{print $NF}' file
/work/foo/processed/25
/work/foo/processed/myproxy
/work/foo/processed/sample
perl -lanF"\s+" -e 'print #F[-1] unless /^Found/' file
Here is an explanation of the command-line switches used:
-l: remove line break from each line of input, then add one back on print
-a: auto-split each line of input into an #F array
-n: loop through each line of input
-F: the regexp pattern to use for the auto-split (with -a)
-e: the perl code to execute (for each line of input if using -n or -p)
If you want to just output the last portion of your directory path, and the basedir is always '/work/foo/processed', I would do this:
perl -nle 'print $1 if m|/work/foo/processed/(\S+)|' file
Try this out :
<Your Command> | grep -P -o '[\/\.\w]+$'
OR if the directory '/work/foo/processed' is always static then:
<Your Command>| grep -P -o '\/work\/foo\/processed\/.+$'
-o : Show only the part of a matching line that matches PATTERN.
-P : Interpret PATTERN as a Perl regular expression.
In this example, the last word in the input will be matched .
(The word can also contain dot(s)),so file names like 'text_file1.txt', can be matched).
Ofcourse, you can change the pattern, as per your requirement.
If you know the columns will be the same, and you always list the full path name, you could try something like:
ls -l | cut -c79-
which would cut out the 79th character until the end. That might work in this exact case, but I think it would be better to find the basename of the last field. You could easily do this in awk or perl. Respond if this is not what you want and I'll add the awk and perl versions.
take the output of your ls command and pipe it to awk
your command|awk -F'/' '{print $NF}'
your_command | perl -pe 's#.*/##'