Passing command line arguments to R CMD BATCH

前端 未结 6 632
你的背包
你的背包 2020-11-27 09:22

I have been using R CMD BATCH my_script.R from a terminal to execute an R script. I am now at the point where I would like to pass an argument to

相关标签:
6条回答
  • 2020-11-27 09:55

    You need to put arguments before my_script.R and use - on the arguments, e.g.

    R CMD BATCH -blabla my_script.R
    

    commandArgs() will receive -blabla as a character string in this case. See the help for details:

    $ R CMD BATCH --help
    Usage: R CMD BATCH [options] infile [outfile]
    
    Run R non-interactively with input from infile and place output (stdout
    and stderr) to another file.  If not given, the name of the output file
    is the one of the input file, with a possible '.R' extension stripped,
    and '.Rout' appended.
    
    Options:
      -h, --help        print short help message and exit
      -v, --version     print version info and exit
      --no-timing           do not report the timings
      --            end processing of options
    
    Further arguments starting with a '-' are considered as options as long
    as '--' was not encountered, and are passed on to the R process, which
    by default is started with '--restore --save --no-readline'.
    See also help('BATCH') inside R.
    
    0 讨论(0)
  • 2020-11-27 10:00

    Here's another way to process command line args, using R CMD BATCH. My approach, which builds on an earlier answer here, lets you specify arguments at the command line and, in your R script, give some or all of them default values.

    Here's an R file, which I name test.R:

    defaults <- list(a=1, b=c(1,1,1)) ## default values of any arguments we might pass
    
    ## parse each command arg, loading it into global environment
    for (arg in commandArgs(TRUE))
      eval(parse(text=arg))
    
    ## if any variable named in defaults doesn't exist, then create it
    ## with value from defaults
    for (nm in names(defaults))
      assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]))[[1]])
    
    print(a)
    print(b)
    

    At the command line, if I type

    R CMD BATCH --no-save --no-restore '--args a=2 b=c(2,5,6)' test.R
    

    then within R we'll have a = 2 and b = c(2,5,6). But I could, say, omit b, and add in another argument c:

    R CMD BATCH --no-save --no-restore '--args a=2 c="hello"' test.R
    

    Then in R we'll have a = 2, b = c(1,1,1) (the default), and c = "hello".

    Finally, for convenience we can wrap the R code in a function, as long as we're careful about the environment:

    ## defaults should be either NULL or a named list
    parseCommandArgs <- function(defaults=NULL, envir=globalenv()) {
      for (arg in commandArgs(TRUE))
        eval(parse(text=arg), envir=envir)
    
      for (nm in names(defaults))
        assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]), envir=envir)[[1]], pos=envir)
    }
    
    ## example usage:
    parseCommandArgs(list(a=1, b=c(1,1,1)))
    
    0 讨论(0)
  • 2020-11-27 10:02

    In your R script, called test.R:

    args <- commandArgs(trailingOnly = F)
    myargument <- args[length(args)]
    myargument <- sub("-","",myargument)
    print(myargument)
    q(save="no")
    

    From the command line run:

    R CMD BATCH -4 test.R
    

    Your output file, test.Rout, will show that the argument 4 has been successfully passed to R:

    cat test.Rout
    
    > args <- commandArgs(trailingOnly = F)
    > myargument <- args[length(args)]
    > myargument <- sub("-","",myargument)
    > print(myargument)
    [1] "4"
    > q(save="no")
    > proc.time()
    user  system elapsed 
    0.222   0.022   0.236 
    
    0 讨论(0)
  • 2020-11-27 10:03

    I add an answer because I think a one line solution is always good! Atop of your myRscript.R file, add the following line:

    eval(parse(text=paste(commandArgs(trailingOnly = TRUE), collapse=";")))
    

    Then submit your script with something like:

    R CMD BATCH [options] '--args arguments you want to supply' myRscript.R &
    

    For example:

    R CMD BATCH --vanilla '--args N=1 l=list(a=2, b="test") name="aname"' myscript.R &
    

    Then:

    > ls()
    [1] "N"    "l"    "name"
    
    0 讨论(0)
  • 2020-11-27 10:11

    My impression is that R CMD BATCH is a bit of a relict. In any case, the more recent Rscript executable (available on all platforms), together with commandArgs() makes processing command line arguments pretty easy.

    As an example, here is a little script -- call it "myScript.R":

    ## myScript.R
    args <- commandArgs(trailingOnly = TRUE)
    rnorm(n=as.numeric(args[1]), mean=as.numeric(args[2]))
    

    And here is what invoking it from the command line looks like

    > Rscript myScript.R 5 100
    [1]  98.46435 100.04626  99.44937  98.52910 100.78853
    

    Edit:

    Not that I'd recommend it, but ... using a combination of source() and sink(), you could get Rscript to produce an .Rout file like that produced by R CMD BATCH. One way would be to create a little R script -- call it RscriptEcho.R -- which you call directly with Rscript. It might look like this:

    ## RscriptEcho.R
    args <- commandArgs(TRUE)
    srcFile <- args[1]
    outFile <- paste0(make.names(date()), ".Rout")
    args <- args[-1]
    
    sink(outFile, split = TRUE)
    source(srcFile, echo = TRUE)
    

    To execute your actual script, you would then do:

    Rscript RscriptEcho.R myScript.R 5 100
    [1]  98.46435 100.04626  99.44937  98.52910 100.78853
    

    which will execute myScript.R with the supplied arguments and sink interleaved input, output, and messages to a uniquely named .Rout.

    Edit2:
    You can run Rscript verbosely and place the verbose output in a file.

    Rscript --verbose myScript.R 5 100 > myScript.Rout
    
    0 讨论(0)
  • After trying the options described here, I found this post from Forester in r-bloggers . I think it is a clean option to consider.

    I put his code here:

    From command line

    $ R CMD BATCH --no-save --no-restore '--args a=1 b=c(2,5,6)' test.R test.out &
    

    Test.R

    ##First read in the arguments listed at the command line
    args=(commandArgs(TRUE))
    
    ##args is now a list of character vectors
    ## First check to see if arguments are passed.
    ## Then cycle through each element of the list and evaluate the expressions.
    if(length(args)==0){
        print("No arguments supplied.")
        ##supply default values
        a = 1
        b = c(1,1,1)
    }else{
        for(i in 1:length(args)){
          eval(parse(text=args[[i]]))
        }
    }
    
    print(a*2)
    print(b*3)
    

    In test.out

    > print(a*2)
    [1] 2
    > print(b*3)
    [1]  6 15 18
    

    Thanks to Forester!

    0 讨论(0)
提交回复
热议问题