Creating executable R scripts

The mathematics package R has the ability to run scripts in its programming language; one can either redirect a file from stdin (with a command line like  R <myRscript), or execute it from the interactive prompt by using the source function (> source("myRscript")).  While this is handy, it seemed to me that it would be nice to be able to write executable R scripts capable of taking command-line parameters, as with sh, perl, tcl/tk and other scripting languages; in short, to use the #! convention with R.

When R starts, it will source the file named in environment variable R_PROFILE before beginning interactive execution.  If that file defines a function named .First, that function will be executed. The Bourne shell script presented below, named setR, takes advantage of R_PROFILE and .First to provide a #! equivalent for R scripts. If the first line of an R script contains  #! /bin/sh /usr/bin/setR  (with the appropriate paths, of course), and the R script is executed, it will be passed by setR to the R interpreter.  An array called argv will be created and passed as well, containing any command-line arguments given with the invocation of the executable R script.

Here's the code. This script is copyright © 2003 Gregory Louis, and is distributed without warranty under the GNU General Public License (GPL):

#! /bin/sh

# command-line args to pass to R
Rargs="--no-save -q"

if [ "x$1" = "xh" -o "x$1" = "x-h" ]; then
    cat <<EOT
NAME
    setR - wrapper to provide a hashbang equivalent for R scripts
SYNOPSIS
    setR -h
      or
    #! /bin/sh /usr/bin/setR
DESCRIPTION
    setR writes an R profile in $TMPDIR containing a function .First that
    sources the calling script. If there are any command-line parameters
    in the invocation of the calling script, these are assigned to
    array argv before function .First's "source" command. If not, argv
    will exist with length 0. R is then called with this profile and
    command-line arguments $Rargs.
OPTIONS
    -h	The option -h displays help.
EOT
    exit 0
fi

# get the name of the calling script; if ./something, replace . with $PWD
caller=$1; shift
test "x${caller#./}" != "x$caller" && caller=$PWD${caller#.}

# begin an R profile with standard options, and startup function .First
profn=$TMPDIR/R$$; test "x$TMPDIR" = "x" && profn=/tmp/R$$
cat > $profn <<-EOT
	options(CRAN="http://cran.us.r-project.org", papersize="letter")
	par(las=1, font.lab=2, pty="s", tcl=0.35, mgp=c(2.75,0.5,0), bty="l")
	.First <- function() {
EOT
# NB: *** for R 2.0.0 and later, omit the par() call from the above! 
# Due to "lazy loading," graphics calls don't work at this point.

# make a comma-separated list of command-line arguments, if any
echo -n "    argv <<- c(" >> $profn
while [ "x$1" != "x" ]; do
    echo -n "\"$1\"" >> $profn; shift
    test "x$1" != "x" && echo -n ", " >> $profn
done
echo ")" >> $profn

# let the .First function end by feeding the calling script to R
cat >> $profn <<-EOT
	    source("$caller")
	}
EOT

# run R and then delete the profile
R_PROFILE=$profn /usr/bin/R $Rargs
/bin/rm -f $profn