# Reading from STDIN, or: how to pipe data into Mathematica

Today I tried using Mathematica's plotting capabilities to display the output of a C++ program. This made me wonder whether it is possible to somehow tell a Mathematica script to read from STDIN and then do something with that, a la

#/usr/local/bin/MathematicaScript -script

(* Mathematica plotting script *)
plot = ListPlot[data];
Export[plot, ...];


which can then be used like

./cppDataGenerator | mathematicaPlotScript


However, I couldn't find much on that in the documentation, the entries always focus on output or string streams, and trial and error didn't yield a result either.

So the question is: How can I make a Mathematica script listen on the standard input?

• I can't test without Linux but can you try Input["!cat","String"] or something similar? Perhaps also try "!cat -". Note this is untested and just a guess!! – Szabolcs Mar 24 '12 at 16:26
• Another thing: this is a good question of course, but if you only use the C++ code with Mma, you can use LibraryLink for easier and more reliable communication. – Szabolcs Mar 24 '12 at 16:29

## Standard input

Try using the Input and or InputString commands to read from the standard input. For example a program that does

Print[InputString[]];


when run on the commandline with

\$>  echo "Hello" | mathematicaScript
Hello


Of course this also works from the standard Mathematica workbook.

## From Invoked program

Use Import with a "!" before the shell command. For example:

Import["!help", "string"]


You may use any valid format that the Import function supports.

You can simply use

ReadList["!program"]


possible specifying an input type (Number, String, etc.) in ReadList. While Read reads only until a newline, ReadList will read until an EOF character.

I have tested this on Windows (with math.exe -script) using the GnuWin32 version of cat and it worked.

• ReadString["!cat"] is also useful here. I must say I don't really understand why your answer works, but that makes it more impressive that you found out about it. – Jacob Akkerboom Dec 14 '15 at 17:08
• @JacobAkkerboom I didn't actually know about ReadString, it seems to be new in 10. Why are you saying that you didn't expect ReadList to work? It reads expressions by default, which is convenient for numbers, bt otherwise dangerous ... ReadList["!prog", String"] is safer ... – Szabolcs Dec 15 '15 at 11:26
• my confusion was more about this use of cat without arguments. But I see now the line in man page of cat (CAT(1)): "If file is a single dash (-') or absent, cat reads from the standard input". I am still impressed that cat connects to the standard input of the script correctly. – Jacob Akkerboom Dec 15 '15 at 12:09
• @JacobAkkerboom I do not remember why I wrote this. It might have been an unfortunate example ... or maybe on Windows this brings up a command prompt where one can type? It's more likely that it's just a bad example. I'll correct it. – Szabolcs Dec 15 '15 at 12:48

Extending on nixeagle's answer, here's what I've come up with.

First of all, the thing I overlooked is the 3rd/5th bullet point when clicking More Information in the help for Input/InputString, it could not be hidden any better:

When no front end is used, Input reads from standard input.

Well that answers that, the rest was finding out how these two functions work. To my knowledge, their difference is that InputString reads STDIN like any other language, while Input interprets STDIN as Mathematica input directly; therefore, I assume that, for practical purposes, Input[] == ToExpression[InputString[]].

So let's try that out:

#!/usr/local/bin/MathematicaScript -script
Print@Input[];

> echo "2^10" | ./mscript
1024


Now back to my plotting problem, there is still an issue: Input seems to stop reading when it encounters a new line, which is of course not desired when giving a large file to the script; I'd much rather have it stop at the EOF byte. However, I wasn't able to find a setting that changes this behavior.

• mind if I extend mine with your notes on the difference between Input and InputString? And are you sure that it quits parsing after a new line even when passed vie a pipe? If so, and you are on GNU/Linux, may I suggest sed? You could transform all the newlines to something like say... \t (tab) or \0` (null) for use as a separator. – nixeagle Mar 24 '12 at 16:56
• Yes you may, no I am not sure (it does on my system at least), and using sed to get rid of all newlines may be a working hack, but I'm looking for a more complete solution. – David Mar 24 '12 at 18:45