Raw text strings for file paths in R - r

Is it possible to use a prefix when specifying a filepath string in R to ignore escape characters?
For example if I want to read in the file example.csv when using windows, I need to manually change \ to / or \\. For example,
'E:\DATA\example.csv'
becomes
'E:/DATA/example.csv'
data <- read.csv('E:/DATA/example.csv')
In python I can prefix my string using r to avoid doing this (e.g. r'E:\DATA\example.csv'). Is there a similar command in R, or an approach that I can use to avoid having this problem. (I move between windows, mac and linux - this is just a problem on the windows OS obviously).

You can use file.path to construct the correct file path, independent of operating system.
file.path("E:", "DATA", "example.csv")
[1] "E:/DATA/example.csv"
It is also possible to convert a file path to the canonical form for your operating system, using normalizePath:
zz <- file.path("E:", "DATA", "example.csv")
normalizePath(zz)
[1] "E:\\DATA\\example.csv"
But in direct response to your question: I am not aware of a way to ignore the escape sequence using R. In other words, I do not believe it is possible to copy a file path from Windows and paste it directly into R.
However, if what you are really after is a way of copying and pasting from the Windows Clipboard and get a valid R string, try readClipboard
For example, if I copy a file path from Windows Explorer, then run the following code, I get a valid file path:
zz <- readClipboard()
zz
[1] "C:\\Users\\Andrie\\R\\win-library\\"

It is now possible with R version 4.0.0. See ?Quotes for more.
Example
r"(c:\Program files\R)"
## "c:\\Program files\\R"

If E:\DATA\example.csv is on the clipboard then do this:
example.csv <- scan("clipboard", what = "")
## Read 1 item
example.csv
## [1] "E:\\DATA\\example.csv"
Now you can copy "E:\\DATA\\example.csv" from the above output above onto the clipboard and then paste that into your source code if you need to hard code the path.
Similar remarks apply if E:\DATA\example.csv is in a file.
If the file exists then another thing to try is:
example.csv <- file.choose()
and then navigate to it and continue as in 1) above (except the file.choose line replaces the scan statement there).
Note that its not true that you need to change the backslashes to forward slashes for read.csv on Windows but if for some reason you truly need to do that translation then if the file exists then this will translate backslashes to forward slashes (but if it does not exist then it will give an annoying warning so you might want to use one of the other approaches below):
normalizePath(example.csv, winslash = "/")
and these translate backslashes to forward slashes even if the file does not exist:
gsub("\\", "/", example.csv, fixed = TRUE)
## [1] "E:/DATA/example.csv"
or
chartr("\\", "/", example.csv)
## [1] "E:/DATA/example.csv"
In 4.0+ the following syntax is supported. ?Quotes discusses additional variations.
r"{E:\DATA\example.csv}"
EDIT: Added more info on normalizePath.
EDIT: Added (4).

A slightly different approach I use with a custom made function that takes a windows path and corrects it for R.
pathPrep <- function() {
cat("Please enter the path:\\n\\n")
oldstring <- readline()
chartr("\\\\", "/", oldstring)
}
Let's try it out!
When prompted paste the path into console or use ctrl + r on everything at once
(x <- pathPrep())
C:/Users/Me/Desktop/SomeFolder/example.csv
Now you can feed it to a function
shell.exec(x) #this piece would work only if
# this file really exists in the
# location specified
But as others pointed out what you want is not truly possible.

No, this is not possible with R versions before 4.0.0. Sorry.

I know this question is old, but for people stumbling upon this question in recent times, wanted to share that with the latest version R4.0.0, it is possible to parse in raw strings. The syntax for that is r"()". Note that the string goes in the brackets.
Example:
> r"(C:\Users)"
[1] "C:\\Users"
Source: https://cran.r-project.org/doc/manuals/r-devel/NEWS.html
jump to section: significant user-visible changes.

Here's an incredibly ugly one-line hack to do this in base R, with no packages necessary:
setwd(gsub(", ", "", toString(paste0(read.table("clipboard", sep="\\", stringsAsFactors=F)[1,], sep="/"))))
Usable in its own little wrapper function thus (using suppressWarnings for peace of mind):
> getwd()
[1] "C:/Users/username1/Documents"
> change_wd=function(){
+ suppressWarnings(setwd(gsub(", ", "", toString(paste0(read.table("clipboard", sep="\\", stringsAsFactors=F)[1,], sep="/")))))
+ getwd()
+ }
Now you can run it:
#Copy your new folder path to clipboard
> change_wd()
[1] "C:/Users/username1/Documents/New Folder"

To answer the actual question of "Can I parse raw-string in R without having to double-escape backslashes?" which is a good question, and has a lot of uses besides the specific use-case with the clipboard.
I have found a package that appears to provide this functionality:
https://github.com/trinker/pathr
See "win_fix".
The use-case specified in the docs is exactly the use-case you just stated, however I haven't investigated whether it handles more flexible usage scenarios yet.

Related

How to dump png to stdout? [duplicate]

Is it possible to get R to write a plot in bitmap format (e.g. PNG) to standard output? If so, how?
Specifically I would like to run Rscript myscript.R | other_prog_that_reads_a_png_from_stdin. I realise it's possible to create a temporary file and use that, but it's inconvenient as there will potentially be many copies of this pipeline running at the same time, necessitating schemes for choosing unique filenames and removing them afterwards.
I have so far tried setting outf <- file("stdout") and then running either bitmap(file=outf, ...) or png(filename=outf, ...), but both complain ('file' must be a non-empty character string and invalid 'filename' argument, respectively), which is in line with the official documentation for these functions.
Since I was able to persuade R's read.table() function to read from standard input, I'm hoping there's a way. I wasn't able to find anything relevant here on SO by searching for [r] stdout plot, or any of the variations with stdout replaced by "standard output" (with or without double quotes), and/or plot replaced by png.
Thanks!
Unfortunately the {grDevices} (and, by implication, {ggplot2}) seems to fundamentally not support this.
The obvious approach to work around this is: let a graphics device write to a temporary file, and then read that temporary file back into the R session and write it to stdout.
But this fails because, on the one hand, the data cannot be read into a string: character strings in R do not support embedded null characters (if you try you’ll get an error such as “nul character not allowed”). On the other hand, readBin and writeBin fail because writeBin categorically refuses to write to any device that’s hooked up to stdout, which is in text mode (ignoring the fact that, on POSIX system, the two are identical).
This can only be circumvented in incredibly hacky ways, e.g. by opening a binary pipe to a command such as cat:
dev_stdout = function (underlying_device = png, ...) {
filename = tempfile()
underlying_device(filename, ...)
filename
}
dev_stdout_off = function (filename) {
dev.off()
on.exit(unlink(filename))
fake_stdout = pipe('cat', 'wb')
on.exit(close(fake_stdout), add = TRUE)
writeBin(readBin(filename, 'raw', file.info(filename)$size), fake_stdout)
}
To use it:
tmp_dev = dev_stdout()
contour(volcano)
dev_stdout_off(tmp_dev)
On systems where /dev/stdout exists (which are most but not all POSIX systems), the dev_stdout_off function can be simplified slightly by removing the command redirection:
dev_stdout_off = function (filename) {
dev.off()
on.exit(unlink(filename))
fake_stdout = file('/dev/stdout', 'wb')
on.exit(close(fake_stdout), add = TRUE)
writeBin(readBin(filename, 'raw', file.info(filename)$size), fake_stdout)
}
This might not be a complete answer, but it's the best I've got: can you open a connection using the stdout() command? I know that png() will change the output device to a file connection, but that's not what you want, so it might work to simply substitute png by stdout. I don't know enough about standard outputs to test this theory, however.
The help page suggests that this connection might be text-only. In that case, a solution might be to generate a random string to use as a filename, and pass the name of the file through stdout so that the next step in your pipeline knows where to find your file.

How to do encoding in R and why ’ comes instead of apostrophe(')s and how to resolve it

Hi I am trying to do text mining in R version 3.4.2
I am trying to import .txt files from local drive using VCorpus command.
But after Run following code
cname <- file.path("C:", "texts")
cname
dir(cname)
library(readr)
library(tm)
docs <- VCorpus(DirSource(cname))
summary(docs)
inspect(docs[1])
writeLines(as.character(docs[1]))
Output:
Well, the election, it came out really well. Next time we**’**ll triple the number and so on
’ its originally aporstophe(')s now how can i convert or get original text in Rstudio?
Please it will appreciate if someone help me
Thanks in Advance
Encoding issues are not easy to solve, since they depend on various factors (file ecnoding, encoding settings during loading, etc.). As a first step you might try the following line, if we are lucky it solves your problem.
Encoding(your_text) <- "UTF-8"
Otherwise, other solutions have to be chekced, e.g., using stri_trans from stringi package or replacing wrong symbols with brute force via gsub(falsecharacter, desiredcharacter, fixed = TRUE) (there are debugging tables, e.g., on i18nqa.com).
I solved this a different way.
I found that apostrophes that looked like this: ' would render properly, while ones that looked slightly different, like this: ’ would not.
So, for any text that I was printing, I converted ’ to ' like this:
mytext <- gsub("’", "'", mytext )
Tada... no more issues with "’".

RStudio addin to parse input string literals by changing backslashes (as in 'C:\Marketing') into forward slashes

Clarification
Solving this problem with a function was not possible, which #IInspectable kindly confirmed in the comments under the old, deleted, question. Long story short: backslashes need to be escaped in string literals, i.e. a 'C:\\Marketing' needs to be passed instead of 'C:\Marketing'. I am fully aware of this and this question and my answer below is not about the error thrown, manual solutions or using other software (e.g. AutoHotkey) as given in other related questions.
Please note the question is a follow up of another one, thank you #IInspectable for your valuable comments.
"Windows" paths...
I do work with Windows formatted paths (like C:\Marketing) quite often by pasting them into R code. Changing the backslashes every time is highly annoying, thus I have attempted to write a parsing function for them. The desired usage was to use this function in the code with the copied path as a parameter, i.e. path_parse('C:\Marketing'). My first approach, based on #Tyler Rinker answer from here, was as following:
path_parse <- function(path = 'clipboard') {
path <- if (path == 'clipboard') readClipboard() else path
return(chartr('\\', '/', path))
}
and it was working nicely with the path copied to the clipboard, but unfortunately was throwing an error message an unrecognized escape in character string, as in e.g. this question, when used with pasted string literals:
> path_parse('C:\Marketing')
Error: '\M' is an unrecognized escape in character string starting "'C:\M"
Of course manually changing all the input string literals (as in passing 'C:\\Marketing' or 'C:/Marketing' instead of 'C:\Marketing') is not an option here, as this is exactly why I want to automate it somehow.
One closely related question to this one is here, but it is based on Tinn-R GUI and AutoHotkey software, which I do not want to install.
Addins to the rescue
The solution was closer than I thought, an RStudio addin (see e.g. here how to use them) parsing the selected text (i.e. the pasted "Windows" path) by changing all backslashes into forward slashes and inserting it back into the code. Code and screenshots in the answer below.
A working solution (or rather a workaround, as initially I wanted to solve this with a function)
As I wrote in the question above, solving this problem with a function was not possible, so I tried a different solution, which is doing exactly what I wanted, and might be useful for others as well. I have built an addin package (a nice article by RStudio) with the following function:
#' Parse selected "Windows" path to an "R-usable" one
#'
#' #return
#' #export
#' #importFrom rstudioapi getActiveDocumentContext
#' #importFrom magrittr '%>%'
#'
#' #examples
path_parse <- function() {
getActiveDocumentContext()[['selection']][[1]][['text']] %>%
{ gsub('\\\\', '/', .) } %>%
{ gsub('//', '/', .) } %>% # To remove double f. slashes
{ ifelse(check_for_quotes(.), insertText(.), insertText(paste0('\'', ., '\''))) }
}
### Old function:
# path_parse <- function() {
# getActiveDocumentContext()[['selection']][[1]][['text']] %>%
# { chartr('\\', '/', .) } %>% { insertText(paste0('\'', ., '\'')) }
# }
and assigned a Ctrl+Alt+P shortcut to it.
What it does is, basically, parsing the selected text (i.e. the pasted "Windows" path) by changing all backslashes into forward slashes and inserting it back into the code:

Copy script after executing

Is there a possibility to copy the executed lines or basically the script into the working directory?
So my normal scenario is, I have stand alone script which just need to be sourced within a working directory and they will do everything I need.
After a few month, I made update to these scripts and I would love to have a snapshot from the script when I executed the source...
So basically file.copy(ITSELF, '.') or something like this.
I think this is what you're looking for:
file.copy(sys.frame(1)$ofile,
to = file.path(dirname(sys.frame(1)$ofile),
paste0(Sys.Date(), ".R")))
This will take the current file and copy it to a new file in the same directory with the name of currentDate.R, so for example 2015-07-14.R
If you want to copy to the working directory instead of the original script directory, use
file.copy(sys.frame(1)$ofile,
to = file.path(getwd(),
paste0(Sys.Date(), ".R")))
Just note that the sys.frame(1)$ofile only works if a saved script is sourced, trying to run it in terminal will fail. It is worth mentioning though that this might not be the best practice. Perhaps looking into a version control system would be better.
Explanation:
TBH, I might not be the best person to explain this (I copied this idea from somewhere and use it sometimes), but I'll try. Basically in order to have information about the script file R needs to be running it as a file inside an environment with that information, and when that environment is a source call it contains the ofile data. We use (1) to select the next (source()'s) environment following the global environment (which is 0). When you're running this from terminal, there's no frame/environment other than Global (that's the error message), since no file is being ran - the commands are sent straight to terminal.
To illustrate that, we can do a simple test:
> sys.frame(1)
Error in sys.frame(1) : not that many frames on the stack
But if we call that from another function:
> myf <- function() sys.frame(1)
> myf()
<environment: 0x0000000013ad7638>
Our function's environment doesn't have anything in it, so it exists but, in this case, does not have ofile:
> myf <- function() names(sys.frame(1))
> myf()
character(0)
I just wanted to add my solution since I decided to use a try function before executing the copy command... Because I have the feeling I miss some control...
try({
script_name <- sys.frame(1)$ofile
copy_script_name <-
paste0(sub('\\.R', '', basename(script_name)),
'_',
format(Sys.time(), '%Y%m%d%H%M%S'),
'.R')
file.copy(script_name,
copy_script_name)
})
This will copy the script into the current directory and also adds a timestamp to the filename. In case something goes wrong, the rest of the script will still execute.
I originally posted this other thread, and I think it addresses your problem: https://stackoverflow.com/a/62781925/9076267
In my case, I needed a way to copy the executing file to back up the original >script together with its outputs. This is relatively important in research.
What worked for me while running my script on the command line, was a mixure of >other solutions presented here, that looks like this:
library(scriptName)
file_dir <- paste0(gsub("\\", "/", fileSnapshot()$path, fixed=TRUE))
file.copy(from = file.path(file_dir, scriptName::current_filename()) ,
to = file.path(getwd(), scriptName::current_filename()))
Alternatively, one can add to the file name the date and our to help in >distinguishing that file from the source like this:
file.copy(from = file.path(current_dir, current_filename()) ,
to = file.path(getwd(), subDir, paste0(current_filename(),"_", Sys.time(), ".R")))

How to rename file without changing the modified date

I wrote a script to rename files. But I found the modified date were changed to same. So the original order is broken if they are sorted by date. Is there any way to change the names without changing the modified date? Or although the dates are changed, the order is still the same if they are sorted by date. The following is my current code:
# save previous working folder
wkdir <- getwd()
# set the target folder
setwd("C:/Users/YY/Desktop/Tmp file/")
# set the file pattern
a <- list.files(path = ".", pattern = "abc_*.*$")
# set the name to be replaced
b<-gsub("abc_","ABC_",a)
# rename
file.rename(a,b)
# restore previous working folder
setwd(wkdir)
I would appreciate it if anyone can help me.
I had the same question - I needed to process files, then archive. I tried in R first, then realized the copy changed the original datetime stamp for the file.
I eventually learned the shell() command and solved it with code like below. As I am in Windows OS, I used -R and -d in filenames to denote whether in form for R (/ form in path) or Windows (\ form in path) and converted using normalizePath().
sourcefileR <- "c:/Users/myname/Documents/test.dat"
destfileR <- "c:/Users/myname/Documents/somewhereelse/test.dat"
sourcefiled <- normalizePath(sourcefileR)
# now looks like: "c:\\Users\\myname\\Documents\\test.dat"
destfiled <- normalizePath(destfileR)
rept <- shell(paste("copy ", sourcefiled, destfiled, sep=" "), intern=TRUE)
The intern parameter causes the OS feedback to go into the R object rept, which can be searched to find the "1 file(s) copied" string for success or whatever other error trapping you want.
I am in R version 2.15.3 (2013-03-01) on Platform: x86_64-w64-mingw32/x64 (64-bit)
running Windows 7 Professional, SP1.
Of course it is possible!
Instead of using a command like "REN" or "RENAME", you can use the "MOVE" command for renaming your files/folders and their dates will stay exactly the same.
Example:
MOVE "C:\Folder\Filename.txt" "C:\Folder\New_Filename.txt"
(I don't know if it's working for all versions of Windows but it's seem to be working at least for Windows 7)
If for some reason you can't use the MOVE command, there is a program like Nircmd from Nirsoft that can change the file dates to any dates you want.
Syntax:
nircmd.exe setfiletime "creation-time" "modified-time"
Example:
nircmd.exe setfiletime "c:\temp\myfile.txt" "24-06-2003 17:57:11" "22-11-2005 10:21:56"
You can't change names without changing the modification date. Think about that for a moment! You're modifying the file (even though you're not modifying the content).
Q. Are you sorting in R or outside in Windows folder view?
Q. Have you thought about sorting by creation date?
If you're sorting in windows, you should be able to figure out how to sort by "Creation Date"
and if you're sorting it in R, use file.info to get relevant attributes and then sort on that.

Resources