Passing arguments from a call to a bash script to an Rscript - r

I have a bash script that does some things and then calls Rscript. Here a simple example to illustrate:
test.sh:
Rscript test.r
test.r:
args <- commandArgs()
print(args)
How can I use ./test.sh hello on the command line result in R printing hello?

You can have bash pass all the arguments to the R script using something like this for a bash script:
#!/bin/bash
Rscript /path/to/R/script --args "$*"
exit 0
You can then choose how many of the arguments from $* need to be discarded inside of R.

I noticed the way to deal with this is:
test.sh:
Rscript test.r $1
test.r:
args <- commandArgs(TRUE)
print(args)
The $1 represents the first argument passed to the bash script.
When calling commandArgs() instead of commandArgs(TRUE), it does not pass from bash, but instead it will print other arguments called internally.

Regarding asb's answer:
having "--args" in the line of bash script doesn't work, the "--args" was taken as the literal of real argument that I want to pass into my R script. Taking it out works, i.e. "Rscript /path/to/my/rfile.R arg1 arg2"
bash version: GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Rscript version: R scripting front-end version 3.0.1 (2013-05-16)

Related

How to set shell used by system() to invoke bash scripts in R? [duplicate]

I have to run a shell script inside R. I've considered using R's system function.
However, my script involves source activate and other commands that are not available in /bin/sh shell. Is there a way I can use /bin/bash instead?
Thanks!
Invoke /bin/bash, and pass the commands via -c option in one of the following ways:
system(paste("/bin/bash -c", shQuote("Bash commands")))
system2("/bin/bash", args = c("-c", shQuote("Bash commands")))
If you only want to run a Bash file, supply it with a shebang, e.g.:
#!/bin/bash -
builtin printf %q "/tmp/a b c"
and call it by passing script's path to the system function:
system("/path/to/script.sh")
It is implied that the current user/group has sufficient permissions to execute the script.
Rationale
Previously I suggested to set the SHELL environment variable. But it probably won't work, since the implementation of the system function in R calls the C function with the same name (see src/main/sysutils.c):
int R_system(const char *command)
{
/*... */
res = system(command);
And
The system() library function uses fork(2) to create a child process that executes the shell command specified in command using execl(3) as follows:
execl("/bin/sh", "sh", "-c", command, (char *) 0);
(see man 3 system)
Thus, you should invoke /bin/bash, and pass the script body via the -c option.
Testing
Let's list the top-level directories in /tmp using the Bash-specific mapfile:
test.R
script <- '
mapfile -t dir < <(find /tmp -mindepth 1 -maxdepth 1 -type d)
for d in "${dir[#]}"
do
builtin printf "%s\n" "$d"
done > /tmp/out'
system2("/bin/bash", args = c("-c", shQuote(script)))
test.sh
Rscript test.R && cat /tmp/out
Sample Output
/tmp/RtmpjJpuzr
/tmp/fish.ruslan
...
Original Answer
Try to set the SHELL environment variable:
Sys.setenv(SHELL = "/bin/bash")
system("command")
Then the commands passed to system or system2 functions should be invoked using the specified shell.

UNIX commands from R via shell function

I need to issue unix commands from an R session. I'm on Windows R2 2012 server using RStudio 1.1.383 and R 3.4.3.
The shell() function looks to be the right one for me but when I specify the path to my bash shell (from Git for Windows install) the command fails with error code 127.
shell_path <- "C:\\Program Files\\Git\\git-bash.exe"
shell("ls -a", shell = shell_path)
## running command 'C:\Program Files\Git\git-bash.exe /c ls -a' had status 127'ls -a' execution failed with error code 127
Pretty sure my shell path is correct:
What am I doing wrong?
EDIT: for clarity I would like to pass any number of UNIX commands, I am just using ls -a for an example.
EDIT:
After some playing about 2018-03-09:
shell(cmd = "ls -a", shell = '"C:/Program Files/Git/bin/bash.exe"', intern = TRUE, flag = "-c")
The correct location of my bash.exe was at .../bin/bash.exe. This uses shell with intern = TRUE to return the output as an R object. Note the use of single quote marks around the shell path.
EDIT: 2018-03-09 21:40:46 UT
In RStudio we can also call bash using knitr and setting chunk options:
library(knitr)
```{bash my_bash_chunk, engine.path="C:\\Program Files\\Git\\bin\\bash.exe"}
# Using a call to unix shell
ls -a
```
Two things stand out here. Bash will return exit code 127 if a command is not found; you should try running the fully qualified command name.
I also see that your shell is being run with a /c flag. According to the documentation, the flag argument specifies "the switch to run a command under the shell" and it defaults to /c, but "if the shell is bash or tcsh or sh the default is changed to '-c'." Obviously this isn't happening for git-bash.exe.
Try these changes out:
shell_path <- "C:\\Program Files\\Git\\git-bash.exe"
shell("/bin/ls -a", shell = shell_path, flag = "-c")
Not on Windows, so can't be sure this will work.
Perhaps you need to use shQuote?
shell( paste("ls -a ", shQuote( shell_path) ) )
(Untested. I'm not on Windows. But do read ?shQuote))
If you just want to do ls -a, you can use the below commands:
shell("'ls -a'", shell="C:\\Git\\bin\\sh.exe")
#or
shell('C:\\Git\\bin\\sh.exe -c "ls -a"')
Let us know if the space in "Program Files" is causing problems.
And if you require login before you can call your command,
shell('C:\\Git\\bin\\sh.exe --login -c "ls -a"')
But if you are looking at performing git commands from R, the git2r by ropensci might suit your needs.

Passing SLURM batch command line arguments to R

I'm trying to run a SLURM sbatch command with various parameters that I can read in an R script. When using PBS system, I used to write qsub -v param1=x,param2=y (+ other system parameters like the memory requirements etc and the script name to be read by PBS) and then in the R script read it with x = Sys.getenv(‘param1’).
Now I tried
sbatch run.sh --export=basePath=‘a’
With run.sh:
#!/bin/bash
cd $SLURM_SUBMIT_DIR
echo $PWD
module load R/common/3.3.3
R CMD BATCH --quiet --no-restore --no-save runDo.R output.txt
And runDo.R:
base.path = Sys.getenv('basePath')
print(base.path)
The script is running but the argument value is not assigned to base.path variable (it prints an empty string).
The export parameter has to be passed to sbatch not to the run.sh script.
It should be like this:
sbatch --export=basePath=‘a’ run.sh

Specify which shell to use in R

I have to run a shell script inside R. I've considered using R's system function.
However, my script involves source activate and other commands that are not available in /bin/sh shell. Is there a way I can use /bin/bash instead?
Thanks!
Invoke /bin/bash, and pass the commands via -c option in one of the following ways:
system(paste("/bin/bash -c", shQuote("Bash commands")))
system2("/bin/bash", args = c("-c", shQuote("Bash commands")))
If you only want to run a Bash file, supply it with a shebang, e.g.:
#!/bin/bash -
builtin printf %q "/tmp/a b c"
and call it by passing script's path to the system function:
system("/path/to/script.sh")
It is implied that the current user/group has sufficient permissions to execute the script.
Rationale
Previously I suggested to set the SHELL environment variable. But it probably won't work, since the implementation of the system function in R calls the C function with the same name (see src/main/sysutils.c):
int R_system(const char *command)
{
/*... */
res = system(command);
And
The system() library function uses fork(2) to create a child process that executes the shell command specified in command using execl(3) as follows:
execl("/bin/sh", "sh", "-c", command, (char *) 0);
(see man 3 system)
Thus, you should invoke /bin/bash, and pass the script body via the -c option.
Testing
Let's list the top-level directories in /tmp using the Bash-specific mapfile:
test.R
script <- '
mapfile -t dir < <(find /tmp -mindepth 1 -maxdepth 1 -type d)
for d in "${dir[#]}"
do
builtin printf "%s\n" "$d"
done > /tmp/out'
system2("/bin/bash", args = c("-c", shQuote(script)))
test.sh
Rscript test.R && cat /tmp/out
Sample Output
/tmp/RtmpjJpuzr
/tmp/fish.ruslan
...
Original Answer
Try to set the SHELL environment variable:
Sys.setenv(SHELL = "/bin/bash")
system("command")
Then the commands passed to system or system2 functions should be invoked using the specified shell.

for loop of subjobs using qsub R

I am trying to run subjobs (one for each chromosome) using R --vanilla. Since each chromosome is independent I want them to run parallel in the system. I have written the following script:
#!/bin/bash
for K in {20..21};
do
qsub -V -cwd -b y -q short.q R --vanilla --args arg1$K arg2$K arg3$K < RareMETALS.R > loggroup$K.txt; done
But somehow R opens interactively and not in command line as suppose... when trying the script itself
R --vanilla --args arg1 arg2 arg3 < RareMETALS.R > loggroup.txt; done
It runs perfectly calling the script.
Can someboby guide me, or point out which might be the problem.
My take on this would be to use echo instead of --args option to pass parameters to the script. I find separating the script and the Grid Engine code to be more straightforward:
for K in {20..21};
do
echo "Rscript RareMETALS.R arg1$K arg2$K arg3$K > loggroup$K.txt" | qsub -V -cwd -q short.q
done
As others have commented use Rscript.
Code seems cleaner to me, but there may be some limitations to using echo as opposed to --args I am unaware of.

Resources