MathGroup Archive 2007

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: Issue

  • To: mathgroup at smc.vnet.net
  • Subject: [mg73554] Re: [mg66602] Re: Issue
  • From: "Chris Chiasson" <chris at chiasson.name>
  • Date: Wed, 21 Feb 2007 06:06:03 -0500 (EST)
  • References: <e2ppk1$t2i$1@smc.vnet.net> <4450BD11.4080601@gmail.com>

I believe I figured out what happened to the Run command on Windows
and why it sometimes requires an extra set of quotation marks. The
reason is given directly in the output of the help command. Just type

C:\>help cmd

in a DOS box. After the description of the command line switches,
there are two paragraphs and a numbered list. Read the second
paragraph and the numbered list. Also, read the description for the /S
command line switch.

It should then be plain what cmd is doing. cmd is stripping the outer
quotation marks and then processing the command.

For instance, this command works well from a regular command line:

C:\>"C:\Program Files\test.bat" "hi up"

However, if one isn't mindful of the rules above, the following
command might be expected to work:

C:\>cmd /c "C:\Program Files\test.bat" "hi up"

However, according to the processing rules given in the help output,
the first and last quotation marks are stripped, leading to the error:

'C:\Program' is not recognized as an internal or external command,
operable program or batch file.

To avoid this behavior, the /s switch can be fed to cmd and the
argument to cmd can always be quoted:

C:\>cmd /s /c ""C:\Program Files\test.bat" "hi up""

Anyway, I believe the failure to add the outer quotation marks and the
/s switch is a problem with Mathematica, and that the run command
should be altered appropriately in the next version.

For those that do not want to wait, Robby Villegas' trap method works
quite well for overloading Run to always add outer quotation marks
(but you won't be able to add the /s switch, so things may not always
work out properly):

Unprotect@Run;
Update@Run;
$TrapRun=True
Run[args__]/;$TrapRun:=
    Block[{$TrapRun=False},
      Run["\""<>StringJoin@
            BoxForm`Intercalate[ToString[#,InputForm]&/@{args}," "]<>"\""]];
Update@Run;
Protect@Run;

P.S. Does anyone know why Update is sometimes needed when unprotecting
variables? I just add the statements out of habit right now.


On 5/22/06, Chris Chiasson <chris.chiasson at gmail.com> wrote:
> Rui Liu of WRI tech support has this to say about Run:
>
> Hello,
>
> Thank you for the email.
>
> My apologies for the delay in getting back to you regarding this.
>
> The following is a fairly technical description, but it shows what's
> really
> going on,
>
> First let's see how the function Run[] works currently.
>
> All of the argument strings are StringJoined together into a single
> string, with spaces between each argument.  (This means there's
> really nothing special to using the multi-argument form.  From now
> on, here the single-argument form of Run is used for simplicity.)
>
>  Run["dir",".exe"]  -->  Run["dir *.exe"]
>
> Then that string is passed to the C function system().
>
> Now, on Windows, system() takes the string its given and precedes it
> with the string "cmd /c ".  This runs the standard Windows shell
> cmd.exe, sometimes called the "DOS prompt," with the /c argument
> meaning "run the following command, and return when finished."
>
> So, for instance, Run["dir *.exe"] eventually becomes (inside
> the C run-time library), a call to start "cmd.exe" with a command
> line of:
>        cmd.exe /c dir *.exe
>
> Here is how you can use this information to decide how to quote
> things for Run:  try your example out on in the command prompt.
> You can get a command prompt in Windows by going to the Start menu,
> choosing Run, and entering "cmd" into the Run box.  This will give
> you a command prompt window.
>
> For instance:
> (1) Should you add special quotes to either dir or *.exe?
>
>    Try at the command prompt:
>      cmd.exe /c dir *.exe
>    and you see this works fine without adding quotes.  So in
> Mathematica:
>      Run["dir *.exe"]
>    works fine, too.
>
> (2) What about getting a directory of C:\Program Files\Windows NT\*.exe
> ?
>
>    Try at the command prompt:
>      cmd.exe /c dir C:\Program Files\Windows NT\*.exe
>    This doesn't work.  So let's try some quote marks:
>      cmd.exe /c dir "C:\Program Files\Windows NT\*.exe"
>    This does work (it will show dialer.exe and HYPERTRM.EXE).
>
>    So this means it needs to add explicit quote marks when the function
>    Run[] is called:
>      In[1]:= Run["dir \"C:\\Program Files\\Windows NT\\*.exe\""]
>    (Notice that I had to "escape" both the double-quotes and the
>     path-separating backslashes.)
>
> A lot of the weird behavior of Run is coming from the weird behavior
> of cmd.exe, really.  So playing around with cmd can help you figure out
> what you need to pass to Run to make it work.
>
> Also, while fiddling with the Run[] function it can be best to use
> math.exe
> rather than Mathematica.exe.  The reason is that
> math.exe outputs to the console (the command prompt window that
> cmd.exe uses), so you can see any error messages that cmd.exe prints
> along with Mathematica's output.
>
> Here let's look at your examples:
>
> (1) How to run something in a directory with spaces.  Try this in
>    cmd.exe first:
>
>    C:\> cmd /c C:\Documents and Settings\user\finalproject.bat hi up
>    'C:\Documents' is not recognized as an internal or external command,
>    operable program or batch file.
>
>    It's treating the first space as the end of the program name to run,
>    and all the words that follow (starting with "and") as arguments to
>    this nonexistent program "C:\Documents".  So let's quote the program
>    name:
>
>    C:\> cmd /c "C:\Documents and Settings\user\finalproject.bat" hi up
>    hello hi what is up
>
>    That works, so it means that Run needs quotes around the program
> name:
>
>    In[1]:= Run["\"C:\\Documents and Settings\\user\\finalproject.bat\"
> hi
> up"]
>
> (2) What about quoting both the program name and the arguments?
>    Here we seem to run into a bug in cmd.exe.
>
>    C:\> cmd /c "C:\Documents and Settings\user\finalproject.bat" "hi
> up"
>    'C:\Documents' is not recognized as an internal or external command,
>    operable program or batch file.
>
>    That seems wrong.  It ought to run the program with one argument,
> the
>    string "hi up", displaying:   hello "hi up" what is
>    But instead it gets totally confused.
>
>    So let's play around with more quotes, by putting quotes around each
>    element, AND around the whole thing.
>
>    C:\> cmd /c ""C:\Documents and Settings\user\finalproject.bat" "hi
> up""
>    hello "hi up" what is
>
>    Success!  I don't know why.  But this tell you what you have to do
> if
>    you want to Run a program with spaces in its name that takes
> arguments
>    with spaces in them:  quote both the executable path, the arguments,
>    and the whole thing.
>
>    In[2]:= Run["\"\"C:\\Documents and
> Settings\\user\\finalproject.bat\"
> \"hi up\"\""]
>    hello "hi up" what is
>
> (3) This double-double-quoting approach also works when the executable
> path
>    name doesn't have any spaces in it.
>
>    C:\> cd "Documents and Settings"
>    C:\Documents and Settings> cmd /c ""user\finalproject.bat" "hi up""
>    hello "hi up" what is
>
>    And in Mathematica ...
>
>    SetDirectory["C:\\Documents and Settings"]
>    Run["\"\"user\\finalproject.bat\" \"hi up\"\""]
>    hello "hi up" what is
>
> Of course, in the last case you don't really need all the quotes.
> Just Run["user\\finalproject.bat \"hi up\""] will do.  But I believe
> you're trying to come up with some system that is sure to work no
> matter
> whether the path has spaces, or whether the arguments are quoted.
> It looks like the double-double-quote approach does the job.
>
> And remember, if you're having trouble, at all times you can always
> ask cmd.exe /c what it wants.  That's all Run[] is doing.
>
> Sincerely,
>
> Rui Liu
> Technical Support
> Wolfram Research, Inc.
> support at wolfram.com
>
>


-- 
http://chris.chiasson.name/


  • Prev by Date: Re: Re: Issue
  • Next by Date: split
  • Previous by thread: Re: Re: Issue
  • Next by thread: split