2

I am trying to make a R script - test.R - that can take either a file or a text string directly from a pipe in unix as in either:

file | test.R

or:

cat Sometext | test.R

Tried to follow answers here and here but I am clearly missing something. Is it the piping above or my script below that gives me a error like:

me@lnx: cat AAAA | test.R
bash: test.R: command not found
cat: AAAA: No such file or directory

My test script:

#!/usr/bin/env Rscript
input <- file("stdin", "r")
x <- readLines(input)
write(x, "")

UPDATE.

The script:

#!/usr/bin/env Rscript
con <- file("stdin")
open(con, blocking=TRUE)
x <- readLines(con)
x <- somefunction(x) #Do something or nothing with x
write(x,"")
close(con)

Then both cat file | ./test.R and echo AAAA | ./test.R yield the expected.

user3375672
  • 3,728
  • 9
  • 41
  • 70
  • 1
    Regarding your bash, `cat` expects a file, that's why you're getting the `AAAA: no such file or directory` error. And your R file `test.R` usually isn't an executable, hence the `command not found` error. – mickey Dec 01 '18 at 00:14
  • True. In my case it was executable. I think it had something to do with line endings. Deleting excess empty lines (and added back) in nano (or similar) editor appeared to fix that. And the `./` part . – user3375672 Dec 01 '18 at 00:16

2 Answers2

2

I still like r over Rscript here (but then I am not unbiased in this ...)

edd@rob:~$ (echo "Hello,World";echo "Bye,Bye") | r -e 'X <- readLines(stdin());print(X)' -
Hello,World
Bye,Bye
[1] "Hello,World" "Bye,Bye"
edd@rob:~$ 

r can also read.csv() directly:

edd@rob:~$ (echo "X,Y"; echo "Hello,World"; echo "Bye,Bye") | r -d -e 'print(X)' -
      X     Y
1 Hello World
2   Bye   Bye
edd@rob:~$

The -d is essentially a predefined 'read stdin into X via read.csv' which I think I borrowed as an idea from rio or another package.

Edit: Your example works with small changes:

  1. Make it executable: chmod 0755 ex.R
  2. Pipe output in correctly, ie use echo not cat
  3. Use the ./ex.R notation for a file in the current dir
  4. I changed it to use print(x)

Then:

edd@rob:~$ echo AAA | ./ex.R
[1] "AAA"
edd@rob:~$
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Yeah `littler` is definitely something I use often (together with `docopt`) to write small R programs - however, here, I try to get a hang on the connection between stdin and Rscript. – user3375672 Nov 30 '18 at 22:44
  • Working with `stdin` is one of those little things that are easier with `r`. At least to me :) – Dirk Eddelbuettel Nov 30 '18 at 23:01
  • I dont disagree on that (I am the one not understanding `stdin`) - but sometimes you have something more complex than one-liners that you need put into a script file for future use. (And such - I know - can also be interpreted by `littler`) – user3375672 Nov 30 '18 at 23:07
  • Thats great. Got close in the meantime myself. And as a final variation I might need `write(x, "")` to STDOUT. Is it "correct" to make a `close(con)` ? – user3375672 Dec 01 '18 at 00:08
  • Ah yes you should close the connection. – Dirk Eddelbuettel Dec 01 '18 at 00:13
  • The shorthand version with `-d` doesn't work for me. I have an Rscript that just converts input to lowercase and prints it out. The longhand version you showed with `X<-readLines(stdin())` prints out the desired output, whereas the shorthand prints: `"logical(0)"`. When I input two echos chained, it outputs only the last input. – FLonLon Feb 10 '22 at 09:32
0

I generally use R from a terminal application (BASH shell). I have only done a few experiments with Rscript, but including the #! line allows the script to be run in R, while permitting the use of RScript to generate an executable file. I have to use chmod to set the executable flag on my test file. Your call to write() should print the same output to the console in R or RScript, but if I want to save my output to a file I call sink("fileName") to open the connection and sink() to close it. This generally gives me control of the output and how it is rendered. If I called my script "myScript.rs" and made it executable (chmod u+x myScript.rs) I can type something like ./myScript.rs to run it and get the output on OS X or Linux. Instead of a pipe | you might try redirection > or >> to create or append.