Executing expressions in Rscript.exe - r

I'd like to put some expressions that write stuff to a file directly into a call to Rscript.exe (without specifying file in Rscript [options] [-e expression] file [args] and thus without an explicit R script that is run).
Everything seems to work except the fact that the desired file is not created. What am I doing wrong?
# Works:
shell("Rscript -e print(Sys.time())")
# Works:
write(Sys.time(), file='c:/temp/systime.txt')
# No error, but no file created:
shell("Rscript -e write(Sys.time(), file='c:/temp/systime.txt')")

Rscript parses its command line using spaces as separators. If your R string contains embedded spaces, you need to wrap it within quotes to make sure it gets sent as a complete unit to the R parser.
You also don't need to use shell unless you specifically need features of cmd.exe.
system("Rscript.exe -e \"write(Sys.time(), file='c:/temp/systime.txt')\"")

Related

Pass output of R script to bash script

I would like to pass the output of my R file to a bash script.
The output of the R script being the title of a video: "Title of Video"
And my bash script being simply:
youtube-dl title_of_video.avi https://www.youtube.com/watch?v=w82a1FTere5o88
Ideally I would like the output of the video being "Title of Video".avi
I know I can use Rscript to launch an R script with a bash command but I don't think Rscript can help me here.
In bash you can call a command and use its output further via the $(my_command) syntax.
Make sure your script only outputs the title.
E.g.
# in getTitle.R
cat('This is my title') # note, print would have resulted in an extra "[1]"
# in your bash script:
youtube-dl $(Rscript getTitle.R) http://blablabla
If you want to pass arguments to your R script as well, do so inside the $() syntax; if you want to pass those arguments to your bash script, and delegate them to the R script to handle them, you can use the special bash variables $1 (denote the 1st argument, etc), or $* to denote all arguments passed to the bash script, e.g.
#!/bin/bash
youtube-dl $(Rscript getTitle.R $1) http://blablablabla
(this assumes that getTitle.R does something to those arguments internally via commandArgs etc to produce the wanted title output)
You can call Rscript in bash script and you might assign the output of the R script to a variable in bash script. Check this question. After that you can execute
youtube-dl $outputFromRScript https://www.youtube.com/watch?v=w82a1FTere5o88

Can I source ksh and expect in the same script?

I am trying to use environment variables set by ksh and the expect command in the same script. However, if I try to source both of them, it doesnt work. Is there a way to source ksh and expect in the same script?
Do something like
#!/usr/bin/ksh
. /path/to/ksh_stuff.sh
export FOO=bar
# other ksh stuff
expect <<'END_EXPECT'
source /path/to/expect_stuff.exp
send_user "FOO is $env(FOO)\n"
# other expect stuff
END_EXPECT
Adding quotes around the here-doc terminator (<<'END_EXPECT') means that the entire here-doc is single quoted, so ksh will not attempt any parameter substitutions on it. This is a effective way to isolate the expect script's variables from ksh.
In Korn shell you dot in the other script, example:
. ${other_script}
This will run in the same process as the parent script. The other script can see any variables that are defined in the parent script. If you want to sub-shell (to run an external command), then you will need to export any variables first.
If you want to reference environment variables in your expect script, (those that are exported by a ksh script that runs expect in a subshell) then your expect script needs to reference a global array env . For example if your ksh script exports MYPATH variable then subshells to expect, the expect might reference $env(MYPATH)

Can I force Rscript to pass wildcard in command line arguments?

As best as I can sort out (since I haven't had much luck finding documentation of it) when one runs Rscript with a command argument that includes a wildcard *, the argument is expanded to a character vector of the filepaths that match, or passed if there are no matches. Is there a way to pass the wildcard all the time, so I can handle it myself within the script (using things like Sys.glob, for example)?
Here's a minimal example, run from the terminal:
ls
## foo.csv bar.csv baz.txt
Rscript -e "print(commandArgs(T))" *.csv
## [1] "foo.csv" "bar.csv"
Rscript -e "print(commandArgs(T))" *.txt
## [1] "baz.txt"
Rscript -e "print(commandArgs(T))" *.rds
## [1] "*.rds"
EDIT: I have learned that this behavior is from bash, not Rscript. Is there some way to work around this behavior from within R, or to suppress wildcard expansion for a particular R script but not the Rscript command? In my particular case, I want to run a function with two arguments, Rscript collapse.R *.rds out.rds that concatenates the contents of many individual RDS files into a list and saves the result in out.rds. But since the wildcard gets expanded before being passed to R, I have no way of checking whether the second argument has been supplied.
If I understand correctly, you don't want bash to glob the wildcard for you, you want to pass the expression itself, e.g. *.csv. Some options include:
Pass the expression in quoted text and process it within R, either by evaluating that in another command or otherwise
Rscript -e "list.files(pattern = commandArgs(T))" "*\.csv$"
Pass just the extension and process the * within R by context
Rscript -e "list.files(pattern = paste0('*\\\\.', commandArgs(T)))" "csv$"
Through complicated and unnecessary means, disable globbing for that command: Stop shell wildcard character expansion?
Note: I've changed the argument to a regex to prevent it matching too greedily.

executing a script with spaces in the path leading to it

I'm trying to execute a R script which has spaces in the path leading to it. It fails with path not found error. My command looks like this..
Rscript ../A/B C/test.R
I've tried
Rscript "`../A/B C/test.R`"
Rscript "../A/B C/test.R"
Doesn't work. What's going wrong here?
First let's try the obvious, escape the space:
Rscript "../A/B\ C/test.R"
If that doesn't work, cd inside the folder and try calling it from there:
cd A/B\ C/ && Rscript test.r
(Assuming you're in the parent folder)
If is still not working.. maybe is something inside the script.. What do you have in it?
R has problem sometimes managing spaces with single escape characters, so, if -let's say-, inside your script you have:
source("x.r")
And the FULL PATH of x.r has spaces in its name (like being in the same folder as the file in your example..), it can fail due to not finding the file called from inside r.
Then, change the paths INSIDE the script to have double escapes at the spaces
/A/B C/ -> /A/B\\ C/
And try again the previous options i posted.
Tell us what happens!
Make sure you are running your line of code from the Unix shell.
There may be an error in your directory name or file itself. As a test case, you may try the following:
Rscript "/directory/test A/rnorm.R"
rnorm.R being:
x <- rnorm(200, 10, 4)
print(x)
This basically should print the numbers to your Shell.

Have an Rscript read or take input from stdin

I see how to have an Rscript perform the operations I want when given a filename as an argument, e.g. if my Rscript is called script and contains:
#!/usr/bin/Rscript
path <- commandArgs()[1]
writeLines(readLines(path))
Then I can run from the bash command line:
Rscript script filename.Rmd --args dev='svg'
and successfully get the contents of filename.Rmd echoed back out to me. If instead of passing the above argument a filename like filename.Rmd I want to pass it text from stdin, I try modifying my script to read from stdin:
#!/usr/bin/Rscript
writeLines(file("stdin"))
but I do not know how to construct the commandline call for this case. I tried piping in the contents:
cat filename.Rmd | Rscript script --args dev='svg'
and also tried redirect:
Rscript script --args dev='svg' < filename.Rmd
and either way I get the error:
Error in writeLines(file("stdin")) : invalid 'text' argument
(I've also tried open(file("stdin"))). I'm not sure if I'm constructing the Rscript incorrectly, or the commandline argument incorrectly, or both.
You need to read text from the connection created by file("stdin") in order to pass anything useful to the text argument of writeLines(). This should work
#!/usr/bin/Rscript
writeLines(readLines(file("stdin")))

Resources