madness madness - 8 months ago 47
Bash Question

Specify which shell to use in R

I have to run a shell script inside R. I've considered using R's


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?


Answer Source

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:


It is implied that the current user/group has sufficient permissions to execute the script.


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);


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.


Let's list the top-level directories in /tmp using the Bash-specific mapfile:


script <- '
mapfile -t dir < <(find /tmp -mindepth 1 -maxdepth 1 -type d)
for d in "${dir[@]}"
  builtin printf "%s\n" "$d"
done > /tmp/out'

system2("/bin/bash", args = c("-c", shQuote(script)))

Rscript test.R && cat /tmp/out

Sample Output


Original Answer

Try to set the SHELL environment variable:

Sys.setenv(SHELL = "/bin/bash")

Then the commands passed to system or system2 functions should be invoked using the specified shell.