Backticks with single quote inside single quotes

Discussion in 'Perl Misc' started by john.d.russell@gmail.com, Apr 15, 2006.

  1. Guest

    I have a problem that ultimately seems to be a shell problem, but since
    I could work around it in the shell but not in Perl, this seems like
    the most likely group.

    Let's say I've got a file with a single quote in its name, e.g.
    Foo'Bar. I want to include this filename inside a command invoked
    through backticks.

    print `ls -l 'Foo\'Bar'`;

    This produces the error:

    sh: -c: line 1: unexpected EOF while looking for matching `''

    (Which is extra confusing because it looks like the message is trying
    to emulate curly quotes by enclosing the looked-for single-quote
    character with ` on one side and ' on the other.)

    Doing away with backticks doesn't work. system() gives the same error:

    print system("ls -l 'Foo\'Bar'");

    The same thing happens when issuing that exact command in the shell,
    but there I'm free to swap in double quotes. In the actual scenario
    that I've boiled down to this one-liner, I'm constructing a more
    elaborate string literal and interpolating a variable in a certain
    spot, and that variable's value might or might not have a single quote
    embedded in it. So I'm looking for some way to escape the variable's
    value so that it can be substituted without triggering this error when
    the resulting string is passed to the shell.

    I'm running on OS X 10.4, with Perl 5.8.6. I've verified that both
    pdksh and bash give the same error when issuing the command there.

    I've searched the web and this group, but haven't found an example or
    discussion of this same combination of quoting, backticking, and
    escaping.

    Thanks,
    John
     
    , Apr 15, 2006
    #1
    1. Advertising

  2. Denver Guest

    John D Russell wrote:
    >... since I could work around it in the shell


    Since we all are not familiar with OS X, could you tell us this workaround?

    Did you try the obvious escaping of the escape?
    print `ls -l 'Foo\\'Bar'`;

    > ... I've got a file with a single quote in its name, e.g. Foo'Bar.
    > I want to include this filename inside a command invoked through backticks.
     
    Denver, Apr 15, 2006
    #2
    1. Advertising

  3. Denver Guest

    John D Russell wrote:
    >... since I could work around it in the shell


    Because not all of us are familiar with OS X, could you tell us this workaround?

    Did you try the obvious escaping of the escape?
    print `ls -l 'Foo\\\'Bar'`;


    > ... I've got a file with a single quote in its name, e.g. Foo'Bar.
    > I want to include this filename inside a command invoked through backticks.
     
    Denver, Apr 15, 2006
    #3
  4. wrote in news:1145138202.676683.106330
    @j33g2000cwa.googlegroups.com:

    > Let's say I've got a file with a single quote in its name, e.g.
    > Foo'Bar. I want to include this filename inside a command invoked
    > through backticks.
    >
    > print `ls -l 'Foo\'Bar'`;
    >
    > This produces the error:
    >
    > sh: -c: line 1: unexpected EOF while looking for matching `''


    Then enclose the file name in double quotes.

    asu1@Aardvark /cygdrive/c/DOCUME~1/asu1/LOCALS~1/Temp/t
    $ ls -l
    total 1
    -rw-r--r-- 1 asu1 None 0 Apr 15 18:48 Foo'Bar
    -rwxr-xr-x 1 asu1 None 78 Apr 15 18:53 t.pl

    asu1@Aardvark /cygdrive/c/DOCUME~1/asu1/LOCALS~1/Temp/t
    $ cat t.pl
    #!/usr/bin/perl

    use strict;
    use warnings;

    print qx{ls -l "Foo\'Bar"};

    asu1@Aardvark /cygdrive/c/DOCUME~1/asu1/LOCALS~1/Temp/t
    $ ./t.pl
    -rw-r--r-- 1 asu1 None 0 Apr 15 18:48 Foo'Bar

    Sinan
    --
    A. Sinan Unur <>
    (remove .invalid and reverse each component for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Apr 15, 2006
    #4
  5. Denver Guest

    John D Russell wrote:
    > Doing away with backticks doesn't work. system() gives the same error:
    > print system("ls -l 'Foo\'Bar'");
    >
    > The same thing happens when issuing that exact command in the shell,
    > but there I'm free to swap in double quotes.


    In perl you are free to swap in all the quotes you could ever need.
    What happens with print system(qx(ls -l "Foo'Bar"));?
     
    Denver, Apr 15, 2006
    #5
  6. Denver <××DBraughler××@××bwcc·com> wrote in
    news::

    > What happens with print system(qx(ls -l "Foo'Bar"));?


    What do imagine that does? How is trying to execute a directory listing
    useful?

    Sinan

    --
    A. Sinan Unur <>
    (remove .invalid and reverse each component for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Apr 16, 2006
    #6
  7. wrote:
    > Let's say I've got a file with a single quote in its name, e.g.
    > Foo'Bar. I want to include this filename inside a command invoked
    > through backticks.
    >
    > print `ls -l 'Foo\'Bar'`;
    >
    > This produces the error:
    >
    > sh: -c: line 1: unexpected EOF while looking for matching `''

    [...]
    > Doing away with backticks doesn't work. system() gives the same
    > error:
    >
    > print system("ls -l 'Foo\'Bar'");


    Try

    print system("ls", "-l", "Foo'Bar");

    or, since you were obviously interested in the output of ls:

    open(P, '-|', "ls", "-l", "Foo'Bar") or die "cannot invoke ls: $!";
    while (<P>) {
    print;
    }

    Rule of thumb: Never use backticks or the single-argument form of system
    unless you *know* that the command already is a proper command for your
    shell. Especially don't do it if it involves filenames entered by the
    user or read from directories which the user can write.

    (This gets more complicated if you also need pipes and I/O redirection
    in the command you want to invoke - you can then either invoke the shell
    directly or do all of it in Perl)

    hp

    --
    _ | Peter J. Holzer | Löschung von at.usenet.schmankerl?
    |_|_) | Sysadmin WSR/LUGA |
    | | | | Diskussion derzeit in at.usenet.gruppen
    __/ | http://www.hjp.at/ |
     
    Peter J. Holzer, Apr 16, 2006
    #7
  8. Guest

    Yes, I tried zero, one, two, and three backslashes.

    The workaround I referred to (which another poster also suggested) was
    to use double instead of single quotes around the command argument.
    However, this doesn't work in my _real_ case because the actual command
    there is something like:

    `osascript -e '
    tell application "iTunes"
    set track_list to (every track of playlist "Library" whose artist is
    "$artist")
    ....many more lines...
    '`;

    This is an OS X-specific command that runs an Applescript, analogous to
    doing 'perl -e'.

    I use single quotes around the lengthy argument to avoid having to
    escape every instance of double quotes inside the long string literal.
    There are many instances of double quotes in the embedded script, and
    no other instances of single quotes -- except in the rare case where an
    artist name has an apostrophe, for example "Jane's Addiction". So I
    would like to keep all the surrounding quoting conventions if possible,
    not split the entire script into a list of individual words, and just
    find a transformation to do on the value of $artist so that it doesn't
    give an error if it contains a single quote.

    Thanks,
    John
     
    , Apr 16, 2006
    #8
  9. Brian Wakem Guest

    wrote:

    > I have a problem that ultimately seems to be a shell problem, but since
    > I could work around it in the shell but not in Perl, this seems like
    > the most likely group.
    >
    > Let's say I've got a file with a single quote in its name, e.g.
    > Foo'Bar. I want to include this filename inside a command invoked
    > through backticks.
    >
    > print `ls -l 'Foo\'Bar'`;
    >
    > This produces the error:
    >
    > sh: -c: line 1: unexpected EOF while looking for matching `''
    >
    > (Which is extra confusing because it looks like the message is trying
    > to emulate curly quotes by enclosing the looked-for single-quote
    > character with ` on one side and ' on the other.)
    >
    > Doing away with backticks doesn't work. system() gives the same error:
    >
    > print system("ls -l 'Foo\'Bar'");



    Others have shown you how to do it properly. You can also escape it like
    this:

    print `ls -l 'Foo'\''Bar'`;


    --
    Brian Wakem
    Email: http://homepage.ntlworld.com/b.wakem/myemail.png
     
    Brian Wakem, Apr 16, 2006
    #9
  10. Guest

    wrote:
    > Yes, I tried zero, one, two, and three backslashes.
    >
    > The workaround I referred to (which another poster also suggested) was
    > to use double instead of single quotes around the command argument.
    > However, this doesn't work in my _real_ case because the actual command
    > there is something like:


    So then, it is in fact not a workaround. If you find a *real* workaround
    for the shell, you can than adapt it to perl.

    My shell provides no way to escape a ' inside '', because all characters
    other than ' and ! are considered literally, so \ is just a \. Maybe that
    is your problem. So I have to close the single quotes, give an escaped ',
    then re-open the single quotes.

    ## See what the shell would see:
    print "echo 'foo'\\''bar'"
    __END__
    echo 'foo'\''bar'

    ## that looked OK, now actually do it:
    print `echo 'foo'\\''bar'`
    __END__
    foo'bar


    But rather thatn this, I would probably by-pass all of the shell
    interpretation by using the 4+ argument form of the pipe-open as
    Mr. Holzer suggests.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Apr 17, 2006
    #10
  11. Anno Siegel Guest

    <> wrote in comp.lang.perl.misc:
    > Yes, I tried zero, one, two, and three backslashes.
    >
    > The workaround I referred to (which another poster also suggested) was
    > to use double instead of single quotes around the command argument.
    > However, this doesn't work in my _real_ case because the actual command
    > there is something like:
    >
    > `osascript -e '
    > tell application "iTunes"
    > set track_list to (every track of playlist "Library" whose artist is
    > "$artist")
    > ...many more lines...
    > '`;


    You don't seem to do anything with the return value of the backticks.
    Do you need it? Otherwise, use system() instead of backticks.

    > This is an OS X-specific command that runs an Applescript, analogous to
    > doing 'perl -e'.


    It would have been nice if you had given a runnable example of an
    osascript text.

    > I use single quotes around the lengthy argument to avoid having to
    > escape every instance of double quotes inside the long string literal.
    > There are many instances of double quotes in the embedded script, and
    > no other instances of single quotes -- except in the rare case where an
    > artist name has an apostrophe, for example "Jane's Addiction". So I
    > would like to keep all the surrounding quoting conventions if possible,
    > not split the entire script into a list of individual words, and just
    > find a transformation to do on the value of $artist so that it doesn't
    > give an error if it contains a single quote.


    Perl has many quoting mechanisms, use the one(s) that are appropriate for
    your purpose. Also, if you have a situation where quotes must be passed
    to an external program, avoid interpolating a shell. So build the
    components of the command, then use the list form of system() to
    run the command without an intervening shell.

    Something like this:

    # set the artist
    my $artist = 'Phil Ochs';

    # build the applescript text
    my $applescript = <<EOA;
    tell application "iTunes"
    set track_list to (every track of playlist "Library" whose artist is "$artist")
    end tell
    EOA

    # construct the system command
    my @cmd = ( qw( osascript -e), $applescript);

    # run it
    system @cmd and die "boo";

    If you actually want the output of the command, instead of using backticks,
    use open, which also allows you to specify the command as a list and
    avoid the shell:

    open my $script, '-|', @cmd;
    my $ans;
    $ans .= $_ while <$script>;
    close $script or die "bah";

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Apr 17, 2006
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris
    Replies:
    1
    Views:
    13,762
    Oisin
    Mar 24, 2006
  2. Replies:
    3
    Views:
    13,429
  3. Eric Layman
    Replies:
    3
    Views:
    665
    Rad [Visual C# MVP]
    Apr 14, 2007
  4. Evan
    Replies:
    1
    Views:
    421
    Marc 'BlackJack' Rintsch
    Nov 4, 2008
  5. Replies:
    2
    Views:
    137
    slebetman
    Jul 7, 2008
Loading...

Share This Page