I'm trying to run R from the command line using command line arguments. This includes passing in some filepaths as arguments for use inside the script. It all works most of the time, but sometimes the paths have spaces in and R doesn't understand.
I'm running something of the form:
R CMD BATCH --slave "--args inputfile='C:/Work/FolderWith SpaceInName/myinputfile.csv' outputfile='C:/Work/myoutputfile.csv'" RScript.r ROut.txt
And R throws out a file saying
Fatal error: cannot open file 'C:\Work\FolderWith': No such file or directory
So evidently my single quotes aren't enough to tell R to take everything inside the quotes as the argument value. I'm thinking this means I should find a way to delimit my --args using a comma, but I can't find a way to do this. I'm sure it's simple but I've not found anything in the documentation.
The current script is very basic:
ca = commandArgs(trailingOnly=TRUE)
eval(parse(text=ca))
tempdata = read.csv(inputFile)
tempdata$total = apply(tempdata[,4:18], 1, sum)
write.csv(tempdata, outputFile, row.names = FALSE)
In case it's relevant I'm using windows for this, but it seems like it's not a cmd prompt problem.
Using eval(parse()) is probably not the best and most efficient way to parse command line arguments. I recommend to use a package like the optparse to do the parsing for you. Parsing command line args has already been solved, no need to reimplement this. I could imagine that this solves your problems. Although, spaces in path names are a bad idea to begin with.
Alternatively, you could take a very simple approach and pass the arguments like this:
R CMD BATCH --slave arg1 arg2
Where you can retrieve them like:
ca = commandArgs(TRUE)
arg1 = ca[2]
arg2 = ca[3]
This avoids the eval(parse which I think is causing the issues. Finally, you could try and escape the space like this:
R CMD BATCH --slave "C:/spam\ bla"
You could also give Rscript a try, R CMD BATCH seems to be less favored than Rscript.
As an enhancement of #PaulHimestra answer here how you can use Rscript :
you create a launcher.bat ,
echo off
C:
PATH R_PATH;%path%
cd DEMO_PATH
Rscript youscript.R arg1 arg2
exit
with R_PATH something like C:/Program Files/R/R-version
There are many similarities with this post:
R command line passing a filename to script in arguments (Windows)
Also this post is very OS related. My answer applies only to Windows.
Probably what you are looking for is RScript.exe instead of R.exe. The latter has no problem with spaces: path\to\RScript "My script.r".
One boring thing may be searching or setting the path for RScript and doing this every time one updates R.
Among the convenience scripts I have in my search path, I wrote a little facility to run RScript without bothering with paths. Just in case it may be of interest for someone:
#echo off
setlocal
::Get change to file dir par (-CD must be 1st par)
::================================================
Set CHANGEDIR="F"
If /I %1 EQU -cd (
Set CHANGEDIR="T"
SHIFT
)
::No args given
::=============
If [%1] EQU [] GoTo :USAGE
::Get R path from registry
::========================
:: may check http://code.google.com/p/batchfiles for updates on R reg keys
Call :CHECKSET hklm\software\R-core\R InstallPath
Call :CHECKSET hklm\software\wow6432Node\r-core\r InstallPath
if not defined RINSTALLPATH echo "Error: R not found" & goto:EOF
::Detect filepath when arg not starting with "-"
::==============================================
::Note the space after ARGS down here!!!
Set ARGS=
:LOOP
if [%1]==[] (GoTo :ELOOP)
Set ARGS=%ARGS% %1
::Echo [%ARGS%]
Set THIS=%~1
if [%THIS:~0,1%] NEQ [-] (Set FPATH=%~dp1)
SHIFT
GoTo :LOOP
:ELOOP
::echo %FPATH%
::Run Rscript script, changing to its path if asked
::=================================================
If %CHANGEDIR%=="T" (CD %FPATH%)
Echo "%RINSTALLPATH%\bin\Rscript.exe" %ARGS%
"%RINSTALLPATH%\bin\Rscript.exe" %ARGS%
endlocal
:: ==== Subroutines ====
GoTo :EOF
:USAGE
Echo USAGE:
Echo R [-cd] [RScriptOptions] Script [ScriptArgs]
Echo.
Echo -cd changes to script dir. Must be first par.
Echo To get RScript help on options etc.:
Echo R --help
GoTo :EOF
:CHECKSET
if not defined RINSTALLPATH for /f "tokens=2*" %%a in ('reg query %1 /v %2 2^>NUL') do set RINSTALLPATH=%%~b
GoTo :EOF
The script prints the actual RScript invoking line, before running it.
Note that there is an added argument, -cd, to change automatically to the script directory. In fact it is not easy to guess the script path from inside R (and set it with setwd()), in order to call other scripts or read/write data files placed in the same path (or in a relative one).
This (-cd) might possibly make superfluous your other commandargs, as you may find convenient calling them straight from inside the script.
Related
I'm trying to automate my test runner better. For that I need the update file name in a variable. As this name depends on a the version I'm trying to use a find with a pattern to get the file name. That works just fine in bash.
However if I use that same pattern in expect find complains that it can't find anything.
My guess is that expect is doing something to my wildcards. However my experiments with {}, "", '' or \ didn't result in it working.
I guess I could create a helper sh script to write it into a file and then read that file but I don't like that solution and there has to be an option to pass characters with special tcl meaning as arguments.
At the moment my call looks something like this with an absolute path in front of the pattern:
set pattern {[0-9]*/*test*}
set updateFile [exec find ${pattern} -type f]
The result is that find reports '[0-9]*/*test*': No such file or directory. The pattern is what I would expect and when I call find [0-9]*/*test* -type f in bash it results in the expected file path. Find also works fine as long as I don't have any wild cards.
Has anybody an idea what is wrong?
When you run find [0-9]*/*test* -type f in Bash, it's Bash who interprets the wildcard [0-9]*/*test* and expand it to multiple files. And then Bash would pass the expanded multiple files to find. That's to say find never sees the wildcard.
For exec find $pattern -type f, Tcl would not interpret what's in $pattern and pass it directly to find. Unfortunately find also does not interpret the wildcards here so it fails with error like find : '[0-9]*/*test*': No such file or directory.
To work around, you can invoke find with bash -c:
exec bash -c "find $pattern -type f"
I had written a code so that it can read data from a textfile and pop up IP address and send an email in VBScript.
The code ran successfully.
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("Your File Name Here.txt", ForReading)
strSearchString = objFile.ReadAll
objFile.Close
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.Global = True
objRegEx.Pattern = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
Set colMatches = objRegEx.Execute(strSearchString)
If colMatches.Count > 0 Then
For Each strMatch in colMatches
Wscript.Echo strMatch.Value
Next
End If
The requirements have been changed and it is required to run the same process in unix server, so I have to write VBScript so all the above happens in unix.
No, you can't run VBScript on Linux/Unix. You need to re-implement your script in a language that is available on those platforms, like shell (bash, ksh, (t)csh, ...), Perl, Python, or Ruby.
Since your script seems to be extracting IP addresses from text files I'd say that a shell script would be your best choice here. On Linux distributions the default shell usually is bash, so I suggest you start with the Bash Guide for Beginners. The tool you're looking for is grep. Use it with the parameters -P (Perl-style expressions) and -o (show matches only):
grep -Po "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" /path/to/your.txt
Also, the regular expression could be shortened by grouping dot-number segments, e.g. like this:
grep -Po "\d{1,3}(\.\d{1,3}){3}" /path/to/your.txt
If you want to run this from a script, the file should look somewhat like this:
#!/bin/sh
grep -Po "\d{1,3}(\.\d{1,3}){3}" /path/to/your.txt
The shebang defines what interpreter should be used for executing the content.
I am using the shell() command to generate pdf documents from .tex files within a function. This function sometimes gets ran multiple times with adjusted data and so will overwrite the documents. Of course, if the pdf file is open when the .tex file is ran, it generates an error saying it can't run the .tex file. So I want to know whether there are any R or Windows cmd commands which will check whether a file is open or not?
I'm not claiming this as a great solution: it is hacky but maybe it will do. You can make a copy of the file and try to overwrite your original file with it. If it fails, no harm is made. If it succeeds, you'll have modified the file's info (not the contents) but since your end goal is to overwrite it anyway I doubt it will be a huge problem. In either case, you'll be fixed about whether or not the file can be rewritten.
is.writeable <- function(f) {
tmp <- tempfile()
file.copy(f, tmp)
success <- file.copy(tmp, f)
return(success)
}
openfiles /query /v|(findstr /i /c:"C:\Users\David Candy\Documents\Super.xls"&&echo File is open||echo File isn't opened)
Output
592 David Candy 1756 EXCEL.EXE C:\Users\David Candy\Documents\Super.xls
File is open
Findstr returns 0 if found and 1+ if not found or error.
& seperates commands on a line.
&& executes this command only if previous command's errorlevel is 0.
|| (not used above) executes this command only if previous command's errorlevel is NOT 0
> output to a file
>> append output to a file
< input from a file
| output of one command into the input of another command
^ escapes any of the above, including itself, if needed to be passed to a program
" parameters with spaces must be enclosed in quotes
+ used with copy to concatinate files. E.G. copy file1+file2 newfile
, used with copy to indicate missing parameters. This updates the files modified date. E.G. copy /b file1,,
%variablename% a inbuilt or user set environmental variable
!variablename! a user set environmental variable expanded at execution time, turned with SelLocal EnableDelayedExpansion command
%<number> (%1) the nth command line parameter passed to a batch file. %0 is the batchfile's name.
%* (%*) the entire command line.
%<a letter> or %%<a letter> (%A or %%A) the variable in a for loop. Single % sign at command prompt and double % sign in a batch file.
.
--
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.
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')\"")