[vox-tech] quoting question in perl

Jeff Newmiller vox-tech@lists.lugod.org
Sat, 22 Dec 2001 10:22:58 -0800 (PST)


On Sat, 22 Dec 2001, Harry Souders wrote:

> On Thu, Dec 20, 2001 at 05:06:29PM -0800, Peter Jay Salzman wrote:
> > if you have:
> > 
> > system("rm $filename");
> > 
> > and $filename = "a file", you get an error because you're trying to delete
> > two files, "a" and "file".
> > 
> > what's the proper way of quoting $filename so that the shell sees the file
> > "a file" and not the two non-existant files "a" and "file"?
> 
> There are probably better ways, but this might work:
> 
> system("rm -- $filename");

The "--" option handles a different problem.

The rm command, like most *nix commands, accepts various options.  It
cannot tell the difference between an option and a filename that begins
with a dash.  The "--" option prevents rm from interpreting any further
parameters as options, even if they begin with dashes.

The "a file" problem arises in the shell parsing, not the innards of the
command parsing its parameters.  Thus, the rm command posed by pete would
see three parameters: an option, followed by "a" and "file".  The shell
parsing has to be handled properly first in order for rm to have a chance
to do its work.

This is complicated by the fact that Perl is handling escapes and
substitutions in the string, then the shell is handling escapes and 
substitutions, and then it is parsing the result of that,
and then the rm command sees the result of all that.

The rm command should see "a file" as a single string (no quotes).  
Quoting it in the shell with either a single or double quote accomplishes
this.  But you have to encode a string in Perl that it can understand to
create the proper string to give to the shell.

perl source:              shell (after shell expansion):
$x="a file";                              #definition of $x in perl

                          $x="-r tmp"     #definition of $x in shell

system("rm -r tmp");      rm -r tmp       #recursively remove tmp and
                                          #its subdirectory

system("rm -- -r tmp");   rm -- -r tmp    #removes two files: "-r" and tmp

system('rm $x');          rm -r tmp       #single quotes in perl prevent
                                          #expansion in perl
                                          #shell substitutes
                                          #rm recursively deletes tmp

system("rm $x");          rm a file       #double quotes in perl allow
                                          #expansion in perl
                                          #shell never sees $x
                                          #rm sees two arguments

system("rm '$x'");        rm 'a file'     #single quotes inside double
                                          #quotes are part of perl string
                                          #so expansion in perl proceeds
                                          #shell never sees $x
                                          #rm sees one argument

system("rm \"$x\"");      rm "a file"     #same as last example

---------------------------------------------------------------------------
Jeff Newmiller                        The     .....       .....  Go Live...
DCN:<jdnewmil@dcn.davis.ca.us>        Basics: ##.#.       ##.#.  Live Go...
                                      Live:   OO#.. Dead: OO#..  Playing
Research Engineer (Solar/Batteries            O.O#.       #.O#.  with
/Software/Embedded Controllers)               .OO#.       .OO#.  rocks...2k
---------------------------------------------------------------------------