Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Unwanted double-interpolation in string passed to backticks

Reply
Thread Tools

Unwanted double-interpolation in string passed to backticks

 
 
Henry Law
Guest
Posts: n/a
 
      05-28-2004
I think I've done my homework on this, including "How can I call
backticks without shell processing?" in perlfaq8, and a Groups search
on "perl shell escape characters backticks" but I'm none the wiser;
pointers would be welcome.

Here's a test program:
-----------------------
#! /usr/bin/perl

use strict;
use warnings;

print "Enter filename:";
my $filename = <STDIN>;
chomp $filename;

my $ret = `ls -m $filename`;

print "Returned value:$ret\n";
-----------------------

The problem comes when the file name that is entered contains the "$"
character, which in my case it often does. In the test directory
there is a file called "test" and another called "$test". If I run
the program above and enter "test" the result is as expected, thus:

$ ./test
Enter filename:test
Returned value:test

But if I enter the name of the "$test" file, the variable $filename is
interpolated a second time, and since there is no "$test" variable
within the program it comes out as null, thus:

$ ./test
Enter filename:$test
Returned value:bashref.html, c, d, (etc.. the whole directory)

Escaping the $ within the backticks won't work, since I do want Perl
to interpolate $filename, so what to do? My current work-round is a
sub called "shell_execute" which takes the string to be executed
(after one level of interpolation) and then escapes the dollar signs
before running backticks. It works, but ITNABWTDI?

Henry Law <>< Manchester, England
 
Reply With Quote
 
 
 
 
Anno Siegel
Guest
Posts: n/a
 
      05-28-2004
Henry Law <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> I think I've done my homework on this, including "How can I call
> backticks without shell processing?" in perlfaq8, and a Groups search
> on "perl shell escape characters backticks" but I'm none the wiser;
> pointers would be welcome.
>
> Here's a test program:
> -----------------------
> #! /usr/bin/perl
>
> use strict;
> use warnings;
>
> print "Enter filename:";
> my $filename = <STDIN>;
> chomp $filename;
>
> my $ret = `ls -m $filename`;
>
> print "Returned value:$ret\n";
> -----------------------
>
> The problem comes when the file name that is entered contains the "$"
> character, which in my case it often does. In the test directory
> there is a file called "test" and another called "$test". If I run
> the program above and enter "test" the result is as expected, thus:
>
> $ ./test
> Enter filename:test
> Returned value:test
>
> But if I enter the name of the "$test" file, the variable $filename is
> interpolated a second time, and since there is no "$test" variable
> within the program it comes out as null, thus:
>
> $ ./test
> Enter filename:$test
> Returned value:bashref.html, c, d, (etc.. the whole directory)


The unwanted interpolation happens in the shell that is called to
execute "ls". To avoid this, escape the dollar:

$filename =~ s'\$'\\$'g;

Anno
 
Reply With Quote
 
 
 
 
Paul Lalli
Guest
Posts: n/a
 
      05-28-2004
On Fri, 28 May 2004, Henry Law wrote:

> Here's a test program:
> -----------------------
> #! /usr/bin/perl
>
> use strict;
> use warnings;
>
> print "Enter filename:";
> my $filename = <STDIN>;
> chomp $filename;
>
> my $ret = `ls -m $filename`;
>
> print "Returned value:$ret\n";
> -----------------------
>
> The problem comes when the file name that is entered contains the "$"
> character, which in my case it often does. In the test directory
> there is a file called "test" and another called "$test". If I run
> the program above and enter "test" the result is as expected, thus:
>
> $ ./test
> Enter filename:test
> Returned value:test
>
> But if I enter the name of the "$test" file, the variable $filename is
> interpolated a second time, and since there is no "$test" variable
> within the program it comes out as null, thus:
>
> $ ./test
> Enter filename:$test
> Returned value:bashref.html, c, d, (etc.. the whole directory)


Perl is not interpolating your variable a second time. The shell is
interpolating the variable $test. To verify, try entering the command in
your shell, without perl:
ls -m $test

You will see the same results, that is, an entire directory listing. In
the shell, you'd have to do:
ls -m \$test

which should give you the clue of how to solve this. You could search and
replace all 'special' characters to have a backslash precede them.
However, Perl gives you a way to do this:

$return = `ls -m \Q$filename\E`;
or
$filename = quotemeta $filename
$return = `ls -m $filename`;

Read about quotemeta in perldoc -f quotemeta, and \Q in perldoc perlop
under "Quote and Quote-like Operators"

Paul Lalli
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      05-28-2004
Paul Lalli <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> On Fri, 28 May 2004, Henry Law wrote:
>
> > Here's a test program:
> > -----------------------
> > #! /usr/bin/perl
> >
> > use strict;
> > use warnings;
> >
> > print "Enter filename:";
> > my $filename = <STDIN>;
> > chomp $filename;
> >
> > my $ret = `ls -m $filename`;
> >
> > print "Returned value:$ret\n";
> > -----------------------


[...]

> However, Perl gives you a way to do this:
>
> $return = `ls -m \Q$filename\E`;
> or
> $filename = quotemeta $filename
> $return = `ls -m $filename`;
>
> Read about quotemeta in perldoc -f quotemeta, and \Q in perldoc perlop
> under "Quote and Quote-like Operators"


With quotemeta() you'll also escape "/", which is unwanted in file
names.

Anno
 
Reply With Quote
 
Paul Lalli
Guest
Posts: n/a
 
      05-28-2004
On Fri, 28 May 2004, Anno Siegel wrote:

> > However, Perl gives you a way to do this:
> >
> > $return = `ls -m \Q$filename\E`;
> > or
> > $filename = quotemeta $filename
> > $return = `ls -m $filename`;
> >
> > Read about quotemeta in perldoc -f quotemeta, and \Q in perldoc perlop
> > under "Quote and Quote-like Operators"

>
> With quotemeta() you'll also escape "/", which is unwanted in file
> names.


Unneeded, perhaps. But it has no ill effect, at least not with the shell
I'm using (I believe it's bash).

ls -al foo\/bar
has the same effect as
ls -al foo/bar

Are there shells out there that would throw an error at this?

Paul Lalli
 
Reply With Quote
 
Ben Morrow
Guest
Posts: n/a
 
      05-28-2004

Quoth "Henry Law" <(E-Mail Removed)>:
> I think I've done my homework on this, including "How can I call
> backticks without shell processing?" in perlfaq8, and a Groups search
> on "perl shell escape characters backticks" but I'm none the wiser;
> pointers would be welcome.
>
> Here's a test program:
> -----------------------
> #! /usr/bin/perl
>
> use strict;
> use warnings;
>
> print "Enter filename:";
> my $filename = <STDIN>;
> chomp $filename;
>
> my $ret = `ls -m $filename`;
>
> print "Returned value:$ret\n";
> -----------------------
>
> The problem comes when the file name that is entered contains the "$"
> character, which in my case it often does. In the test directory
> there is a file called "test" and another called "$test". If I run
> the program above and enter "test" the result is as expected, thus:
>
> $ ./test
> Enter filename:test
> Returned value:test
>
> But if I enter the name of the "$test" file, the variable $filename is
> interpolated a second time,


By the shell, not Perl.

> and since there is no "$test" variable
> within the program it comes out as null, thus:


You say you've read the faq answer; why didn't you try it?

my $ret = do {
open my $LS, '-|', ls => -m => $filename
or die "can't fork ls: $!";
local $/;
<$LS>;
};

As a separate issue, is possible to define some sort of DESTROY method
to call die automatically if the implicit close at end of scope fails?
It would make this sort of code both safe and clean.

Ben

--
If you put all the prophets, | You'd have so much more reason
Mystics and saints | Than ever was born
In one room together, | Out of all of the conflicts of time.
http://www.velocityreviews.com/forums/(E-Mail Removed) The Levellers, 'Believers'
 
Reply With Quote
 
Henry Law
Guest
Posts: n/a
 
      05-28-2004
On Fri, 28 May 2004 14:51:21 +0000 (UTC), Ben Morrow
<(E-Mail Removed)> wrote:

>You say you've read the faq answer; why didn't you try it?


I did; and of course it worked. But forking sounded like too much
heavy-duty workload for something so trivial, and which I have to do
many times within this particular program, so I ended up with my
current solution, which is the sub which excapes $'s and then executes
the command within backticks.

Henry Law <>< Manchester, England
 
Reply With Quote
 
Ben Morrow
Guest
Posts: n/a
 
      05-28-2004

Quoth "Henry Law" <(E-Mail Removed)>:
> On Fri, 28 May 2004 14:51:21 +0000 (UTC), Ben Morrow
> <(E-Mail Removed)> wrote:
>
> >You say you've read the faq answer; why didn't you try it?

>
> I did; and of course it worked. But forking sounded like too much
> heavy-duty workload for something so trivial, and which I have to do
> many times within this particular program, so I ended up with my
> current solution, which is the sub which excapes $'s and then executes
> the command within backticks.


Backticks perform a fork. If you want to execute an external command,
you *have* to fork.

In fact, the open '-|' answer is lighter, as backticks will fork twice:
once for the shell and again for ls. Avoiding the shell will remove a
completely extraneous process.

Always benchmark before deciding something is 'too heavy-duty'.

Ben

--
Musica Dei donum optimi, trahit homines, trahit deos. |
Musica truces molit animos, tristesque mentes erigit. | (E-Mail Removed)
Musica vel ipsas arbores et horridas movet feras. |
 
Reply With Quote
 
ctcgag@hotmail.com
Guest
Posts: n/a
 
      05-28-2004
"Henry Law" <(E-Mail Removed)> wrote:
> On Fri, 28 May 2004 14:51:21 +0000 (UTC), Ben Morrow
> <(E-Mail Removed)> wrote:
>
> >You say you've read the faq answer; why didn't you try it?

>
> I did; and of course it worked. But forking sounded like too much
> heavy-duty workload for something so trivial,


Do you have any idea how much work qx{} does behind the scenes?

> and which I have to do
> many times within this particular program, so I ended up with my
> current solution, which is the sub which excapes $'s and then executes
> the command within backticks.


Why not use glob? That is probably lighter (or at least as light) than any
shell-based method, and much easier to figure out the escaping for.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      05-28-2004
Paul Lalli <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> On Fri, 28 May 2004, Anno Siegel wrote:
>
> > > However, Perl gives you a way to do this:
> > >
> > > $return = `ls -m \Q$filename\E`;
> > > or
> > > $filename = quotemeta $filename
> > > $return = `ls -m $filename`;
> > >
> > > Read about quotemeta in perldoc -f quotemeta, and \Q in perldoc perlop
> > > under "Quote and Quote-like Operators"

> >
> > With quotemeta() you'll also escape "/", which is unwanted in file
> > names.

>
> Unneeded, perhaps. But it has no ill effect, at least not with the shell
> I'm using (I believe it's bash).
>
> ls -al foo\/bar
> has the same effect as
> ls -al foo/bar
>
> Are there shells out there that would throw an error at this?


I don't know, but the fact that the question even arises makes a case
against using quotemeta to quote strings for a shell. It may work,
but it's not the right tool for the task.

Anno
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
backticks asynchronous? Giles Bowkett Ruby 4 11-20-2006 04:59 AM
handle a pipe (|) character inside backticks? Chris McMahon Ruby 2 10-19-2006 09:30 PM
Lazy fun: Make unary minus silence stderr for backticks Sam Stephenson Ruby 9 11-07-2005 03:36 PM
taint: system vs. backticks and permissions Kristina Clair Perl 0 08-27-2004 03:54 PM
Backticks: What up? Steven Brent Python 6 04-28-2004 03:40 PM



Advertisments