Run system commands or shell scripts from an interactive R session

When you are working in an interactive R shell and need to run some system commands, you can use a base R function system1.

# toy example

The system funtion can also be used to run custom shell scripts, like so,

system(" arg1 arg2")

where is a shell script that does some custom operations with arg1 and arg2. For example, let’s say I want to extract all the lines in a source file that contains the word “NOTE”. Below2 is one such shell script,


if [ -z "$1" ]; then
        echo "Usage: ./ file_with_notes marker"

rm $1.$2 2> /dev/null

echo "# $2 from" $1 >> $1.$2

less $1 | grep $2 >> $1.$2

echo "$2 are saved to file: $1.$2"

The shell script extracts all the lines from the “file_with_notes” (arg1) that contains a word “marker” (arg2) and save it to a new file (with a specific file name). Then, from within an open interactive R shell, I can call the shell script like so:

system(" explore.R NOTE")

This will extracts all lines with “NOTE” in them from explore.R file and save it to explore.R.NOTE.

There are several comments to be made about this approach:

  1. Unless file is already executable from anywhere (i.e., the directory that contains the file is in the PATH), you might have to provide the absolute paths for both files. For example, above snippet won’t work, unless the two files ( and explore.R) are in the same directory.

  2. In order for this shell script to be useful, the source file (explore.R) is assumed to have many lines that contain the marker “NOTE”. The user must have put in conscious efforts to leave “NOTE” marker in explore.R file.

For the most part, once above two limitations are understood and resolved, the shell script can be useful.

Going one step further, if you find yourself using this particular shell script quite often in your data analysis workflow, you can include this shell script as well as the corresponding R wrapper function that calls the shell script (much like system("ls") above) in an R package3.

The two main files (custom shell script and R wrapper function) need to be in a specific directory, respectively.

  1. The custom shell script needs to be in a subdirectory under /inst directory under the package’s root. Let’s say for this example, the file is in /inst/sh directory.

  2. The R wrapper function needs to be in the usual /R directory under the package’s root directory. For this example, the corresponding R wrapper function is called show_notes() and looks like so:

show_notes <- function(src, marker = "NOTE"){

  main_sh <- system.file("sh", "", package = "my_awesome_R_pkg")
  cmd <- paste0(main_sh, " ", src, " ", marker)


Note that R’s base system.file() function is used here to search for the file in a subdirectory /sh under the root directory of installed package, my_awesome_R_pkg.4

Once my_awesome_R_pkg is installed and loaded, you can call this R wrapper function from your open interactive R shell, like so (assuming explore.R file is in the current working directory of the open interactive R session):


This function call will extract all the lines from explore.R file that contains “NOTE” in them and save it to explore.R.NOTE in the same directory as the explore.R.

This approach can be useful, for example, if you want to keep track of intermediate narratives of your data analysis, which is done interactively in an R session with codes from a source file.

  1. Both a newer version function system2 and a relatively new file system operations opackage fs seem great alternatives, but I haven’t tried them yet.

  2. Note that in addition to familiar R code chunks, you can also execute code chunks in other lanauges by calling the target language engine in place of r. For options, see here.

  3. Check out Jim Hester’s 2018 rstudio conference presentation here for motivations and minimal package file structure.

  4. Note that source files in /inst/sh are copied to /sh when R package is installed.