122

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?

Wael
  • 27
  • 6
blahdiblah
  • 30,909
  • 18
  • 92
  • 149

11 Answers11

144

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
Konrad Rudolph
  • 482,603
  • 120
  • 884
  • 1,141
  • 1
    Yes, I think this is the "official" way to do it. – Frank Jul 09 '09 at 14:42
  • 5
    And running `Rscript --help` from the command line will list a lot of useful options that can added to the shebang, such as `--vanilla`. – flodel Dec 04 '12 at 00:35
  • 8
    Let's also mention the `commandArgs` function and the `getopt` and `optparse` packages for parsing the command line. So that arguments and options can also be passed to your scripts when running from the command line. – flodel Dec 04 '12 at 00:36
  • 1
    Notice that this only works if `#!/usr/bin/Rscript` (which is **not** the standard practice for R scripts). – gented Oct 23 '17 at 15:53
18

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.

saffsd
  • 21,564
  • 16
  • 57
  • 65
Jouni K. Seppänen
  • 36,462
  • 5
  • 69
  • 97
11

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
The_Cute_Hedgehog
  • 1,180
  • 10
  • 17
  • 1
    Not "system-wide", but rather `env` would allow you to run the first `Rscript` found in your own `$PATH`, thus allowing one to actually run something _other_ than a system-wide/default `Rscript` (which may not be installed in `/usr/whatever`). I would recommend using `env` for `R` and `Rscript` stuff, since these in particular may not be installed in standard places. (Ordinary `bash` scripts however can typically safely always use `#!/bin/bash`.) – michael Jun 25 '16 at 21:48
  • @michael No, you’re wrong concerning Bash, and this is dangerous advice. The only thing that can be safely hard-coded is `/bin/sh`. Everything else must use `env` lookup. In particular, more often than not Bash is outdated on compute clusters and users have their own custom installations (commonly in `~/.local/bin`, or shared in something like a `/software` NFS mount). Likewise, on macOS, `/bin/bash` is *always* outdated due to licensing issues, and an up to date Bash is more commonly located at `/usr/local/bin/bash` (I realise your comment is 3 years old but this is fairly important.) – Konrad Rudolph Jul 03 '19 at 09:34
  • No, sorry, that is simply not true. You've a strong opinion on the matter, though, so I won't debate the issue. If using `/bin/sh` is, in any circumstances, not also "dangerous", then you have to admit the same could be said for `/bin/bash`. Using `env` is more unpredictable, due to reliable/inconsistent `PATH` settings for different users, but each R user may actually want this behavior, whereas `bash` scripts do not. Lastly, for CI/cloud invoking newer bash scripts, simply invoke them using `/path/to/my/bash myscript` or explicitly set the path & invoke them using `env script`. EOT – michael Jul 07 '19 at 05:23
9

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

I use R --slave -f script

6

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

phatrick
  • 61
  • 1
  • 1
4

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.

hernamesbarbara
  • 6,004
  • 3
  • 23
  • 25
2

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.

Chrismas007
  • 6,002
  • 3
  • 20
  • 45
John
  • 45
  • 1
  • This answer is potentially helpful, since it is unclear which platform (*nix or Mac OS) the OP refers to. With a little re-working (look to format code and remove the apologetic beginning), this would be a good addition to the answers here. – BenBarnes Jan 15 '15 at 11:53
  • 2
    This is another reason to use `#!/usr/bin/env Rscript` instead of a hard-coded path in `R` scripts (and add that long path to your `$PATH`) – michael Jun 25 '16 at 22:00
2

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:~$
Andrew Aylett
  • 36,202
  • 4
  • 63
  • 92
0

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
Tom
  • 11
  • 2
  • 2
    Rather than this (which seems dead), `littler` would certainly be preferred (since it's still alive); or, just use `Rscript` (which actually came out after `littler` was created.) – michael Jun 25 '16 at 22:10
0

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.

ramanujan
  • 5,235
  • 5
  • 28
  • 31
-1

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!

  • 1
    What about different R scripts needing different parameters? What about passing arguments to the R scripts from the command line? – blahdiblah Apr 16 '09 at 06:36