[Rd] aspell(..., dictionaries) incorrectly passes double-quoted arguments via shell() [and a patch]

Henrik Bengtsson hb at biostat.ucsf.edu
Mon Jan 7 03:00:01 CET 2013

Hi, I think I found a bug in aspell() on Windows.  Specifying argument
'dictionaries' for aspell() does not work on Windows, which I believe
is because it tries to pass a quoted command line option via shell().

# Create a text file to be spell checked
> writeLines(c("Hello", "world", "ANOVA"), con="text.txt")

# Check it (word 'babaa' is unknown)
> aspell("text.txt")

# Get a dictionary
> url <- "http://svn.r-project.org/R/trunk/share/dictionaries/en_stats.rds"
> download.file(url, "en_stats.rds", mode="wb")

# Check it
> aspell("text.txt", dictionaries="./en_stats.rds")
Error in aspell("text.txt", dictionaries = "./en_stats.rds") :
  Running aspell failed with diagnostics:
The filename, directory name, or volume label syntax is incorrect.
In addition: Warning message:
In shell(sprintf("%s > %s 2> %s", command, outfile, errfile), input = input,  :
  '"C:\PROGRA~2\Aspell\bin\aspell.exe" -a -p
< C:\Users\hb\AppData\Local\Temp\RtmpueSaQa\aspell1d1c64e663c9 >
C:\Users\hb\AppData\Local\Temp\RtmpueSaQa\xshell1d1c724c140 2>
execution failed with error code 1

(You get a similar error with 'R CMD check' and system environment

I rather sure that the above error occurs because the value for
command line argument '-p' is quoted, i.e.

  -p "C:\Users\hb\AppData\Local\Temp\RtmpueSaQa\aspell_personal1d1c378e3241"

and then passed to shell().  The shell() expands to a system("cmd /c
...") call on Windows, and the handling of quotation marks by "cmd /c"
is rather peculiar (for details see the paragraph starting with "If /C
or /K is specified, then [...] the following logic is used to process
quote (") characters [...]" in 'cmd /?').  Example:

% cmd /c R --slave -e "print(1:3)"
[1] 1 2 3

% cmd /c "R" --slave -e "print(1:3)"
'R" --slave -e "print' is not recognized as an internal or external command,
operable program or batch file.

x:\calmate,R-forge>cmd /c "R" --slave -e print(1:3)
[1] 1 2 3

x:\calmate,R-forge>cmd /c "R" --slave -e 'print(1:3)'
[1] "print(1:3)"

Because the the personal dictionary used by aspell() is passed via
tempfile("aspell_personal", tmpdir=tempdir()) it does not need to be
quoted on Windows, because such a temporary pathname will never
contain spaces, cf. "If the path to the directory contains a space in
any of the components, the path returned will use the shortnames
version of the path" from help("tempdir").  A patch is therefore:

--- aspell.R    2012-10-16 20:17:38.126736100 -0700
+++ aspell,patch.R      2013-01-06 17:45:44.092499300 -0800
@@ -111,7 +111,8 @@
             aspell_write_personal_dictionary_file(words, personal,
                                                   program = program)
             ## </FIXME>
-            control <- c(control, "-p", shQuote(personal))
+            if (.Platform$OS.type != "windows") personal <- shQuote(personal)
+            control <- c(control, "-p", personal)


> sessionInfo()
R Under development (unstable) (2013-01-05 r61554)
Platform: x86_64-w64-mingw32/x64 (64-bit)

[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[5] LC_TIME=English_United States.1252

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

loaded via a namespace (and not attached):
[1] tools_3.0.0

More information about the R-devel mailing list