# Get both output and return code of external program

Run["program"] will run an external program and return the return code.

Import["!program", "String"] will run the program and return the output as a string.

How can I get both the output and the return code? I need a cross platform solution.

It would be nice (but not strictly necessary) to get stderr too. Do we need J/Link to achieve this?

-
Is Run["ls >> /tmp/ls.txt"] what you want ? –  b.gatessucks Mar 31 '13 at 22:44
@b.gatessucks Yes, but that's rather ugly and has its own problems. For example, if I don't want to make a mess, I need to make sure I'm writing into the temp directory; if that has spaces in the path, I need to escape them; and so on –  Szabolcs Mar 31 '13 at 22:47
Can't you use a combination of StringJoin to build the command and FileNameJoin for the output ? –  b.gatessucks Mar 31 '13 at 22:53
@b.gatessucks Yes, of course it's possible, but it's a lot of trouble. Can you show off hand how to do it in a way which will work on all platforms and there won't be problems with spaces in file names or paths? I think even RunThrough had a bug because it didn't handle spaces properly on Windows XP. –  Szabolcs Mar 31 '13 at 22:56
Not helpful: I did Import["!bla ; echo $?"] and knew that last part was the exit status, but that's very far from cross platform – ssch Mar 31 '13 at 23:02 ## 2 Answers I would say JLink is one of the fastest ways to do this. Just use the Runtime to start a process executing your command and collect the exit code too: << JLink RunThroughWithExitCode[cmd_String] := JavaBlock[Module[{ireader, istream, runtime, process, reader}, LoadJavaClass["java.lang.Runtime"]; runtime = RuntimegetRuntime[]; process = runtime@exec[cmd]; process@waitFor[]; istream = process@getInputStream[]; ireader = JavaNew["java.io.InputStreamReader", istream]; reader = JavaNew["java.io.BufferedReader", ireader]; {reader@readLine[], process@exitValue[]} ]]  And then you get RunThroughWithExitCode["uname -a"] (* {Linux lenerd 3.2.0-39-generic #62-Ubuntu SMP Thu Feb 28 00:28:53 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux, 0} *)  The same approach can be used to catch the error stream of the process. When you are on a system with a bash, you could collect everything in the system call itself. This is basically the same idea that was already suggested by @ssch RunThroughWithExitCode2[cmd_String] := ToExpression@Import[ "!out=\"$(eval " <> cmd <> ")\";ret=$?;echo \"{\\\"${out}\\\",\${ret}}\"", "String"]


This works too and gives a list of output and return value

RunThroughWithExitCode2["which math"]
(* {"/usr/local/Wolfram/Mathematica/9.0.1/Executables/math", 0} *)

-
output = {Rest@NestWhileList[ reader@readLine[] &, "", # =!= Null &, 1, Infinity, -1] , process@exitValue[]} or similar to return all lines of the result (possibly want to StringJoin with "\n" inter-spaced) –  ssch Apr 1 '13 at 0:21
@ssch In the version I tested here, I read all output too, but I wanted the function as small as possible. I think the rest can be adapted easily. –  halirutan Apr 1 '13 at 0:22
Agreed, very clear the way it is now! –  ssch Apr 1 '13 at 0:25
Thank you, this spares me a lot of trouble and a lot of Java doc reading –  Szabolcs Apr 1 '13 at 0:31
@Liam Because the output is the data you send to the process. This becomes clear when you read here. Unfortunately, I have not much experience with Windows. –  halirutan Jun 19 '13 at 7:52

For those who will encounter the same problem as mine (and OP's), I added this answer.

Mathematica now(since 10.0.0) has a new built-in function called RunProcess which does exactly what OP asked (including the standard error).

-