11
$\begingroup$

Is it possible to utilize all three: command line arguments, stdin, and stdout all at once in script for Windows? Unix is fairly easy, but I can't get the following to work with Windows.

Using the following as reference args and stdin. I would like the following output.

_ FileNames[] | _ ToLowerCase@in
$\endgroup$
10
+100
$\begingroup$

On Windows, MathKernel.exe launches the kernel running within a window. The standard output is redirected to that window. To avoid this redirection, we must run the kernel as a console application using Math.exe instead:

 "C:\Program Files\Wolfram Research\Mathematica\10.0\Math" ^
   -noprompt ^
   -script C:\Users\a\Desktop\test.m ^
   "data goes here"

Version 10 also has wolfram.exe which does the same thing.


Update: Using DOSKEY

As requested in a comment, we can define a Windows command alias for our script like this:

doskey _="C:\Program Files\Wolfram Research\Mathematica\10.0\Math" -noprompt -script "C:\path\to\script.m" $*

If script.m contains this...

Print @ {"input" -> InputString[], "cmdline" -> $CommandLine}

... then we can have the following exchange on the command line...

C:\> _ arg1 arg2
abcde

... which produces this output:

{"input" -> "abcde", "cmdline" -> {"C:\\Program Files\\Wolfram Research\\Mathematica\\10.0\\Math",
 "-noprompt", "-script", "C:\\path\\to\\script.m", "arg1", "arg2"}}

Update 2: Using a Command File

We can use a Windows command file to emulate the CYGWIN-based pattern established in the answer by @William. First, we create a command file named _.cmd that contains the following lines:

@echo off
"C:\Program Files\Wolfram Research\Mathematica\10.0\Math" ^
  -noprompt -script "%~dp0mmascript.m" %*

Ensure that _.cmd is in a directory that appears on the Windows executable PATH. The current working directory is fine.

Next, in the same directory, create a Mathematica script named mmascript.m with the following commands:

in := ToExpression @ InputString[]
If[Length @ $CommandLine < 5
, Print["no args"]
, Print @ ToExpression @ # & /@ $CommandLine[[5;;]]
]

It only needs to be in the same directory because the command file uses %~dp0 to reference it -- feel free to change that to an absolute pathname if desired.

mmascript.m differs from @William's test.m in that it evaluates all user-supplied arguments instead of just the first.

Here is a session transcript of the command file in action:

C:\Users\wreach> _
"no args"

C:\Users\wreach> _ Sin[Pi/2]
1

C:\Users\wreach> _ in
4 * 5
20

C:\Users\wreach> _ First@FileNames[]
"AppData"

C:\Users\wreach> _ FileNames[] | _ "in // First"
"AppData"

C:\Users\wreach> echo "test" | _ ToUpperCase@in
"TEST"

Note how the last two examples use pipes to feed input to the script. Like the CYGWIN example, the variable in expands to the result of evaluating a string read from stdin.

$\endgroup$
  • $\begingroup$ InputString[] doesn't seem to work in your example program if you attempt to assign the function to a doskey shortcut. $\endgroup$ – William Feb 15 '15 at 22:36
  • $\begingroup$ @William What was the nature of the failure? It all seemed to work for me when I tried it just now on Windows 7: stdin, stdout, command line arguments. I had to avoid breaking the command across lines since DOSKEY uses different escaping conventions than the command processor. Double-check that the defined macro takes the form you expect by inspecting DOSKEY /m. $\endgroup$ – WReach Feb 15 '15 at 23:01
  • $\begingroup$ try echo test | _ arg1 arg2 it fails in W7 because of the nature of the way doskey works. '_' is not a recognized as an internal or external command. $\endgroup$ – William Feb 16 '15 at 0:15
  • $\begingroup$ While _ arg1 arg2 \n t works. stackoverflow.com/questions/17074672/… $\endgroup$ – William Feb 16 '15 at 0:22
  • 1
    $\begingroup$ @William Streams named "stdout" and "stderr" are available, e.g. WriteString["stderr", "bad news!"]. As to re-using a session using only streams and strings, the only approach that comes to mind at the moment is to implement a Telnet-like protocol where Mathematica and the other process take turns sending commands and responses back and forth. MathLink would give complete fine-grained control but would take more effort to set up. $\endgroup$ – WReach Aug 5 '15 at 14:59
2
$\begingroup$

After a lot of thinking and experimenting I have found Cygwin to be the the best option to support both multiple arguments and stdin.

alias _="/cygdrive/c/Program\ Files/Wolfram\ Research/Mathematica/10.0/Math -noprompt -script "C:/Users/a/Desktop/test.m" "$@""
alias ls="_ FileNames[]"

test.m

in:=ToExpression@InputString[];
If[Length@$CommandLine<5,
      Print["no args"],
      Print@ToExpression@$CommandLine[[5]]
]

Command line

_ FileNames[] | _ ToExpression[in][[1]]
$\endgroup$
1
$\begingroup$

Here is completely alternative solution that works similar to #! but for Windows.

@echo off
"C:\Program Files\Wolfram Research\Mathematica\10.0\Math" -noprompt -run "ToExpression@StringJoin@Riffle[Drop[StringSplit[UsingFrontEnd@Import[$CommandLine[[5]], \"Text\"],\"\n\"], 3], \"\n\"];Quit[];" %0 %*
exit

Print[$CommandLine[[6;;]]];
Pause[5];
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.