124
votes

It's very convenient to have R scripts for doing simple plots from the command line. However, running R from bash scripts is not convenient at all. The ideal might be something like

#!/path/to/R
...

or

#!/usr/bin/env R
...

but I haven't been able to make either of those work.

Another option is keeping the scripts purely in R, e.g. script.R, and invoking it with R --file=script.R or similar. However, occasionally a script will rely on obscure command line switches at which point part of the code exists outside the script. Example: sneaking things into R from bash via a local .Rprofile, the desired switches are then everything --vanilla implies except --no-init-file.

Another option is a bash script to store the R flags and be painlessly executable, which then calls the R script. The problem is that this means a single program just got split into two files which now have to be keep in sync, transferred to new machines together, etc.

The option I currently despise least is embedding the R in a bash script:

#!/bin/bash
... # usage message to catch bad input without invoking R
... # any bash pre-processing of input
... # etc
R --random-flags <<RSCRIPT
# R code goes here
RSCRIPT

Everything's in a single file. It's executable and easily handles arguments. The problem is that combining bash and R like this pretty much eliminates the possibility of any IDE not failing on one or the other, and makes my heart hurt real bad.

Is there some better way I'm missing?

11

11 Answers

146
votes

Content of script.r:

#!/usr/bin/env Rscript

args = commandArgs(trailingOnly = TRUE)
message(sprintf("Hello %s", args[1L]))

The first line is the shebang line. It’s best practice to use /usr/bin/env Rscript instead of hard-coding the path to your R installation. Otherwise you risk your script breaking on other computers.

Next, make it executable (on the command line):

chmod +x script.r

Invocation from command line:

./script.r world
# Hello world
18
votes

Try littler. littler provides hash-bang (i.e. script starting with #!/some/path) capability for GNU R, as well as simple command-line and piping use.

11
votes

Miguel Sanchez's response is the way it should be. The other way executing Rscript could be 'env' command to run the system wide RScript.

#!/usr/bin/env Rscript
9
votes

#!/path/to/R won't work because R is itself a script, so execve is unhappy.

I use R --slave -f script

6
votes

If you are interested in parsing command line arguments to an R script try RScript which is bundled with R as of version 2.5.x

http://stat.ethz.ch/R-manual/R-patched/library/utils/html/Rscript.html

4
votes

This works,

#!/usr/bin/Rscript

but I don't know what happens if you have more than 1 version of R installed on your machine.

If you do it like this

#!/usr/bin/env Rscript

it tells the interpreter to just use whatever R appears first on your path.

2
votes

If the program you're using to execute your script needs parameters, you can put them at the end of the #! line:

#!/usr/bin/R --random --switches --f

Not knowing R, I can't test properly, but this seems to work:

axa@artemis:~$ cat r.test
#!/usr/bin/R -q -f
error
axa@artemis:~$ ./r.test
> #!/usr/bin/R -q -f
> error
Error: object "error" not found
Execution halted
axa@artemis:~$
2
votes

Just a note to add to this post. Later versions of R seem to have buried Rscript somewhat. For R 3.1.2-1 on OSX downloaded Jan 2015 I found Rscript in

/sw/Library/Frameworks/R.framework/Versions/3.1/Resources/bin/Rscript

So, instead of something like #! /sw/bin/Rscript, I needed to use the following at the top of my script.

#! /sw/Library/Frameworks/R.framework/Versions/3.1/Resources/bin/Rscript

The locate Rscript might be helpful to you.

0
votes

You might want to use python's rpy2 module. However, the "right" way to do this is with R CMD BATCH. You can modify this to write to STDOUT, but the default is to write to a .Rout file. See example below:

[ramanujan:~]$cat foo.R
print(rnorm(10))
[ramanujan:~]$R CMD BATCH foo.R
[ramanujan:~]$cat foo.Rout

R version 2.7.2 (2008-08-25)
Copyright (C) 2008 The R Foundation for Statistical Computing
ISBN 3-900051-07-0

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

[Previously saved workspace restored]


 ~/.Rprofile loaded.
Welcome at  Fri Apr 17 13:33:17 2009
> print(rnorm(10))
 [1]  1.5891276  1.1219071 -0.6110963  0.1579430 -0.3104579  1.0072677 -0.1303165  0.6998849  1.9918643 -1.2390156
>

Goodbye at  Fri Apr 17 13:33:17 2009
> proc.time()
   user  system elapsed
  0.614   0.050   0.721

Note: you'll want to try out the --vanilla and other options to remove all the startup cruft.

0
votes

Try smallR for writing quick R scripts in the command line:

http://code.google.com/p/simple-r/

(r command in the directory)

Plotting from the command line using smallR would look like this:

r -p file.txt
-1
votes

The following works for me using MSYS bash on Windows - I don't have R on my Linux box so can't try it there. You need two files - the first one called runr executes R with a file parameter

# this is runr
# following is path to R on my Windows machine
# plus any R params you need
c:/r/bin/r --file=$1

You need to make this executable with chmod +x runr.

Then in your script file:

#!runr
# some R commands
x = 1
x

Note the #! runr line may need to include the full path to runr, depending on how you are using the command, how your PATH variable is set etc.

Not pretty, but it does seem to work!