If others are looking for a similar solution, I just wrote a complete replacement for write.csv ( write.csv.minimal.quote ), which is only cited if necessary:
quote.if.required <- function(x, qmethod=c("double", "escape"), sep=",", eol="\n") { qmethod <- match.arg(qmethod) x <- as.character(x) mask.quote.sub <- grepl('"', x, fixed=TRUE) mask.quote.sep <- grepl(sep, x, fixed=TRUE) | grepl(eol, x, fixed=TRUE) qstring <- switch(qmethod, escape="\\\\\"", double="\"\"") x[mask.quote.sub] <- paste0('"', gsub('"', qstring, x[mask.quote.sub]), '"') x[mask.quote.sep & !mask.quote.sub] <- paste0('"', x[mask.quote.sep & !mask.quote.sub], '"') x } write.csv.minimal.quote <- function(x, file="", ..., qmethod=c("double", "escape"), row.names=FALSE, sep=",", eol="\n", quote) { qmethod <- match.arg(qmethod) if (!is.data.frame(x)) { cn <- colnames(x) x <- as.data.frame(x) colnames(x) <- cn } else { cn <- colnames(x) } cn <- quote.if.required(cn, qmethod=qmethod, sep=sep, eol=eol) x <- as.data.frame(lapply(x, quote.if.required, qmethod=qmethod, sep=sep, eol=eol)) if (is.logical(row.names) && row.names) { row.names <- quote.if.required(base::row.names(x), qmethod=qmethod, sep=sep, eol=eol) } else if (is.character(row.names)) { row.names <- quote.if.required(row.names, qmethod=qmethod, sep=sep, eol=eol) } write.table(x, file=file, append=FALSE, sep=",", dec=".", eol="\n", col.names=cn, row.names=row.names, quote=FALSE) }