Bob
Bob

Reputation: 381

A operator to system() in R

I would like to make R a little bit easier to execute system command. Something like ipython vs python. Here are some thoughts:

The first one is easy to accomplish. However, I am stuck with the second one. I found no ways to redefine an operator in R for a string. Then I took a step back, I tried to define a sys(param). But now, I still need to input the quotation marks. e.g. I need to run sys("ls") instead of sys(ls) to list the directory. Is there a way to make the parameter assume it is a string even without the quotation marks? Thanks. Any suggestions are welcome.

Upvotes: 2

Views: 309

Answers (1)

GSee
GSee

Reputation: 49810

Updated to simplify functions (remove a regexp) and add support for character input

You can use match.call inside a function so that you can call the function without using quotation marks like this.

sys <- function(...) {
  command <- match.call()[[2L]]
  if (!is.character(command)) {
    command <- gsub("- ", "-", deparse(command))
  }
  system(command)
}

Now, either of the following are equivalent to system("ls -a")

sys("ls -a")
sys(ls -a)

The sys function above extracts the second component of the call which is the stuff between the parentheses. i.e. ls -a or "ls -a" in these examples. It then passes that to system (through deparse first if it is not character)

[I added support for strings because otherwise it doesn't work with forward slashes, dots, etc. For example, sys(ls /home) does not work, but sys("ls /home") does.]

However, this still requires using parentheses :-(


To avoid the use of parentheses, you can mask an operator. In the initial version of this answer, I showed how to mask ! which is not a good a idea. You suggested using ? in the comments which could be done like this.

`?` <- function(...) {
  command <- match.call()[[2L]]
  if (!is.character(command)) {
    command <- gsub("- ", "-", deparse(command))
  }
  system(command)
} 

Now, this is the same as system("ls -a -l")

?ls -a -l

But, if you need to use forward slashes, you'd have to use quotes like this

?"ls /home"

Alternatively, you could create a special binary operator

"%sys%" <- function(...) {
  system(sub("%sys%", "", deparse(match.call())))
}

You can use it like this

ls %sys% -l
ls %sys% .

If you need to use forward slashes, you have to quote the right side

ls %sys% "/home"

A downside is that it requires exactly one argument on the right side of the operator.

Upvotes: 4

Related Questions