Getting 'system' to Process Win32 Paths Correctly

Discussion in 'Perl Misc' started by Jim Keenan, Jul 14, 2005.

  1. Jim Keenan

    Jim Keenan Guest

    I wish to supply a user with a Perl distribution which includes a
    command-line utility and whose test suite tests the output of that
    utility. The test suite's call to that utility looks like this:

    ok(! system("$^X -I$cwd/blib/lib $cwd/blib/script/utility"),
    "able to call command-line utility");

    where $^X is the name used to execute the current copy of Perl and $cwd
    holds the name of the directory from which the test suite is called,
    i.e., the directory holding Makefile.PL.

    This works fine on my Unix-style system and fine on Win32 *provided*
    that $cwd contains no wordspaces. So if the value of $cwd is
    "C:/temp/other", the 'system' call correctly expands $cwd and the test
    runs as intended.

    However, if the value of $cwd is "C:/Documents and
    Settings/localuser/My Documents", then the only part of the path that
    get substituted is "C:/Documents". The "and" in "Documents and
    Settings" is treated by perl as the program to be run, which causes an
    error.

    I've looked at the documentation for modules such as Cwd and File::Spec
    and I don't see a workaround. So, ...

    Can anyone suggest how to get 'system' to correctly interpret a
    variable which holds a Win32 path which may contain wordspaces?

    Thank you very much.
    Jim Keenan
    Jim Keenan, Jul 14, 2005
    #1
    1. Advertising

  2. Jim Keenan

    Paul Lalli Guest

    Jim Keenan wrote:
    > I wish to supply a user with a Perl distribution which includes a
    > command-line utility and whose test suite tests the output of that
    > utility. The test suite's call to that utility looks like this:
    >
    > ok(! system("$^X -I$cwd/blib/lib $cwd/blib/script/utility"),
    > "able to call command-line utility");
    >
    > where $^X is the name used to execute the current copy of Perl and $cwd
    > holds the name of the directory from which the test suite is called,
    > i.e., the directory holding Makefile.PL.
    >
    > This works fine on my Unix-style system and fine on Win32 *provided*
    > that $cwd contains no wordspaces. So if the value of $cwd is
    > "C:/temp/other", the 'system' call correctly expands $cwd and the test
    > runs as intended.


    I don't think this has anything to do with system(), so much as it has
    to do with standard command line processing. If there are spaces in a
    command line, they're taking to be argument-separators. If you want
    them to mean actual spaces, you have to escape them - either by
    prepending them with a backslash, or by enclosing the entire argument
    in quotes:

    ok(! system(qq|^X -I"$cwd/blib/lib" "$cwd/blib/script/utility"|),
    "able to call command-line utility"

    Paul Lalli
    Paul Lalli, Jul 14, 2005
    #2
    1. Advertising

  3. "Jim Keenan" <> wrote in
    news::

    > I wish to supply a user with a Perl distribution which includes a
    > command-line utility and whose test suite tests the output of that
    > utility. The test suite's call to that utility looks like this:
    >
    > ok(! system("$^X -I$cwd/blib/lib $cwd/blib/script/utility"),
    > "able to call command-line utility");
    >


    ....

    > However, if the value of $cwd is "C:/Documents and
    > Settings/localuser/My Documents", then the only part of the path that
    > get substituted is "C:/Documents".


    The easy way is to wrap the file name in quotation marks:

    system("$^X -Iqq{$cwd/blib/lib} qq{$cwd/blib/script/utility}");

    On the other hand, for better portability, I would construct the
    individual paths using File::Spec::catfile anyway.

    By the way, there is a difference between calling system as above versus

    system($^X, -I$cwd/blib/lib, $cwd/blib/script/utility);

    D:\Home\asu1\UseNet\clpmisc> cat ttt.pl
    #!/usr/bin/perl

    use strict;
    use warnings;

    my $appdata = $ENV{APPDATA};

    system "perl t2.pl $appdata";
    system 'perl', 't2.pl', $appdata;
    __END__

    D:\Home\asu1\UseNet\clpmisc> cat t2.pl
    #!/usr/bin/perl

    use strict;
    use warnings;

    print "$_\n" for @ARGV;

    __END__

    D:\Home\asu1\UseNet\clpmisc> ttt
    C:\Documents
    and
    Settings\asu1\Application
    Data
    C:\Documents and Settings\asu1\Application Data

    Read

    perldoc -f system

    Sinan

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

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
    A. Sinan Unur, Jul 14, 2005
    #3
  4. "Paul Lalli" <> wrote in
    news::

    > Jim Keenan wrote:
    >> I wish to supply a user with a Perl distribution which includes a
    >> command-line utility and whose test suite tests the output of that
    >> utility. The test suite's call to that utility looks like this:
    >>
    >> ok(! system("$^X -I$cwd/blib/lib $cwd/blib/script/utility"),
    >> "able to call command-line utility");
    >>
    >> where $^X is the name used to execute the current copy of Perl and
    >> $cwd holds the name of the directory from which the test suite is
    >> called, i.e., the directory holding Makefile.PL.
    >>
    >> This works fine on my Unix-style system and fine on Win32 *provided*
    >> that $cwd contains no wordspaces. So if the value of $cwd is
    >> "C:/temp/other", the 'system' call correctly expands $cwd and the
    >> test runs as intended.

    >
    > I don't think this has anything to do with system(),


    Indeed it does. There is a difference between passing a single scalar
    string versus a list to system.

    Sinan

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

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
    A. Sinan Unur, Jul 14, 2005
    #4
  5. Jim Keenan

    Paul Lalli Guest

    A. Sinan Unur wrote:
    > "Paul Lalli" <> wrote in
    > news::
    >
    > > Jim Keenan wrote:
    > >> I wish to supply a user with a Perl distribution which includes a
    > >> command-line utility and whose test suite tests the output of that
    > >> utility. The test suite's call to that utility looks like this:
    > >>
    > >> ok(! system("$^X -I$cwd/blib/lib $cwd/blib/script/utility"),
    > >> "able to call command-line utility");
    > >>
    > >> where $^X is the name used to execute the current copy of Perl and
    > >> $cwd holds the name of the directory from which the test suite is
    > >> called, i.e., the directory holding Makefile.PL.
    > >>
    > >> This works fine on my Unix-style system and fine on Win32 *provided*
    > >> that $cwd contains no wordspaces. So if the value of $cwd is
    > >> "C:/temp/other", the 'system' call correctly expands $cwd and the
    > >> test runs as intended.

    > >
    > > I don't think this has anything to do with system(),

    >
    > Indeed it does. There is a difference between passing a single scalar
    > string versus a list to system.


    Hrm. Good point. Trying to see if I understand perldoc -f system
    correctly... so if a single string is passed, system lets the shell
    parse the string into program + arguments, but if a list of more than
    item is passed, system executes the first element, specifying the
    remainder as arguments?

    Good to keep in mind. Thanks for the reminder.

    Paul Lalli
    Paul Lalli, Jul 14, 2005
    #5
  6. "A. Sinan Unur" <> wrote in
    news:Xns969366015F405asu1cornelledu@127.0.0.1:

    > "Jim Keenan" <> wrote in
    > news::
    >
    >> I wish to supply a user with a Perl distribution which includes a
    >> command-line utility and whose test suite tests the output of that
    >> utility. The test suite's call to that utility looks like this:
    >>
    >> ok(! system("$^X -I$cwd/blib/lib $cwd/blib/script/utility"),
    >> "able to call command-line utility");
    >>

    >
    > ...
    >
    >> However, if the value of $cwd is "C:/Documents and
    >> Settings/localuser/My Documents", then the only part of the path that
    >> get substituted is "C:/Documents".

    >
    > The easy way is to wrap the file name in quotation marks:
    >
    > system("$^X -Iqq{$cwd/blib/lib} qq{$cwd/blib/script/utility}");


    And, this, of course, is wrong. The correct version would have been:

    system(qq{$^X -I"$cwd/blib/lib" "$cwd/blib/script/utility"});

    My other comments regarding passing a list to system, and using
    File::Spec::catfile to construct paths still apply, though.

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

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
    A. Sinan Unur, Jul 14, 2005
    #6
  7. Jim Keenan

    Jim Keenan Guest

    A. Sinan Unur wrote:
    > The correct version would have been:
    >
    > system(qq{$^X -I"$cwd/blib/lib" "$cwd/blib/script/utility"});
    >
    >


    Thanks, Sinan, this DWIMmed. A note for further reference: To pare
    the original question down to its essence, I omitted options that the
    command-line utility would normally call. When I tested the real code,
    I had to add them back in. The quoting that worked for them went like
    this:

    ok(! system(qq{$^X -I"$cwd/blib/lib" "$cwd/blib/script/utility" -Icn
    XYZ::ABC}),
    "able to call utility");

    Note that the option flags and arguments are not placed within the
    quotation marks, but are still within the scope of the 'qq{}'.

    Jim Keenan
    Jim Keenan, Jul 14, 2005
    #7
  8. A. Sinan Unur wrote:

    > "Paul Lalli" <> wrote in
    > news::
    >>
    >>I don't think this has anything to do with system(),

    >
    > Indeed it does. There is a difference between passing a single scalar
    > string versus a list to system.


    Except this is Win32 - where there isn't a difference.

    system(LIST) effectively joins the list with spaces and the CLI splits
    it again (in all the wrong places).
    Brian McCauley, Jul 15, 2005
    #8
  9. Brian McCauley <> wrote in news:db8pri$f8g$1
    @redhat2.bham.ac.uk:

    > A. Sinan Unur wrote:
    >
    >> "Paul Lalli" <> wrote in
    >> news::
    > >>
    >>>I don't think this has anything to do with system(),

    >>
    >> Indeed it does. There is a difference between passing a single scalar
    >> string versus a list to system.

    >
    > Except this is Win32 - where there isn't a difference.
    >
    > system(LIST) effectively joins the list with spaces and the CLI splits
    > it again (in all the wrong places).


    I am not sure if you noticed my earlier example. Here is another one of
    system(SCALAR) versus system(LIST). There clearly is a difference.

    D:\Home\asu1\UseNet\clpmisc> cat hello.c
    #include <stdio.h>

    int main(int argc, char *argv[]) {
    int i;
    for(i = 0; i < argc; ++i) {
    printf("%s\n", argv);
    }
    }

    D:\Home\asu1\UseNet\clpmisc> cl hello.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for
    80x86
    Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

    hello.c
    Microsoft (R) Incremental Linker Version 7.10.3077
    Copyright (C) Microsoft Corporation. All rights reserved.

    /out:hello.exe
    hello.obj

    D:\Home\asu1\UseNet\clpmisc> cat ttt.pl
    #!/usr/bin/perl

    use strict;
    use warnings;

    system "hello A. Sinan Unur ---";
    system 'hello', 'A. Sinan Unur', '---';

    D:\Home\asu1\UseNet\clpmisc> ttt.pl
    hello
    A.
    Sinan
    Unur
    ---
    hello
    A. Sinan Unur
    ---

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

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
    A. Sinan Unur, Jul 16, 2005
    #9
    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. Noah
    Replies:
    5
    Views:
    778
  2. Java and Swing
    Replies:
    1
    Views:
    671
    Chris Lambacher
    Oct 24, 2005
  3. Tim Golden
    Replies:
    0
    Views:
    438
    Tim Golden
    Oct 21, 2005
  4. Ohad Lutzky

    Paths, gentleman, paths

    Ohad Lutzky, Nov 6, 2006, in forum: Ruby
    Replies:
    2
    Views:
    188
    David Vallner
    Nov 7, 2006
  5. Aryeh M. Friedman
    Replies:
    1
    Views:
    189
    Aryeh M. Friedman
    Jul 5, 2013
Loading...

Share This Page