What's the best way to use R scripts on the command line (terminal)?

139,021

Solution 1

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

Solution 2

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.

Solution 3

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

Solution 4

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

I use R --slave -f script

Solution 5

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

Share:
139,021
blahdiblah
Author by

blahdiblah

Updated on March 26, 2021

Comments

  • blahdiblah
    blahdiblah about 3 years

    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?

  • blahdiblah
    blahdiblah about 15 years
    What about different R scripts needing different parameters? What about passing arguments to the R scripts from the command line?
  • flodel
    flodel over 11 years
    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
    flodel over 11 years
    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.
  • BenBarnes
    BenBarnes over 9 years
    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.
  • michael
    michael almost 8 years
    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
    michael almost 8 years
    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
    michael almost 8 years
    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
    michael almost 8 years
    Fyi to casual readers: a lot of these answers pre-date Rscript (and littler), in case you're wondering.
  • gented
    gented over 6 years
    Notice that this only works if #!/usr/bin/Rscript (which is not the standard practice for R scripts).
  • Konrad Rudolph
    Konrad Rudolph almost 5 years
    @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
    Konrad Rudolph almost 5 years
    @michael None of the answers here predate Rscript, which was released in 2007 with R 2.5.0.
  • michael
    michael almost 5 years
    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