2011-08-10 11 views
16

He estado jugando un poco con system() y system2() por diversión, y me sorprendió que puedo guardar el estado de salida o de salida en un objeto. Un ejemplo de juguete:Capture el estado de salida y la salida de una llamada al sistema en R

X <- system("ping google.com",intern=TRUE) 

me da la salida, mientras que

X <- system2("ping", "google.com") 

me da el estado de salida (1 en este caso, Google no toma ping). Si quiero tanto el estado de salida como el de salida, tengo que hacer 2 llamadas al sistema, lo que parece un poco exagerado. ¿Cómo puedo obtener ambos con solo una llamada al sistema?

EDIT:. Me gustaría tener tanto en la consola, si es posible, sin pasarse de un archivo temporal mediante stdout="somefile.ext" en la llamada system2 y posteriormente leerlo en

+0

¿Estás utilizando Linux o Windows? Ni siquiera puedo obtener stdout = "somefile.ext" para trabajar en Windows, pero funciona bien en Linux ... – Tommy

+0

Recomiendo agregar 'linux' a tus etiquetas, junto con cualquier shell que estés usando. Esto puede invitar algunas soluciones de los expertos del sistema operativo. – Iterator

+0

Disculpas a OP y @Gavin, puedo estar equivocado: pensé que esto era explícita o implícitamente Linux, pero veo que OP ni siquiera mencionó a Linux y podría ser otro sistema operativo por lo que sé. – Iterator

Respuesta

10

A partir de R 2,15, system2 dará el valor de retorno como un atributo cuando stdout y/o stderr son TRUE. Esto hace que sea más fácil obtener la salida de texto y el valor de retorno.

En este ejemplo, ret termina siendo una cadena con un atributo "status":

> ret <- system2("ls","xx", stdout=TRUE, stderr=TRUE) 
Warning message: 
running command ''ls' xx 2>&1' had status 1 
> ret 
[1] "ls: xx: No such file or directory" 
attr(,"status") 
[1] 1 
> attr(ret, "status") 
[1] 1 
12

estoy un poco confundido por su descripción de system2, porque tiene argumentos stdout y stderr. Por lo tanto, puede devolver tanto el estado de salida, stdout y stderr.

> out <- tryCatch(ex <- system2("ls","xx", stdout=TRUE, stderr=TRUE), warning=function(w){w}) 
> out 
<simpleWarning: running command ''ls' xx 2>&1' had status 2> 
> ex 
[1] "ls: cannot access xx: No such file or directory" 
> out <- tryCatch(ex <- system2("ls","-l", stdout=TRUE, stderr=TRUE), warning=function(w){w}) 
> out 
[listing snipped]     
> ex 
[listing snipped] 
+5

+1 Muy bien. Por cierto, bienvenidos a SO, donde no todos leen la información de ayuda para los comandos de R. ;-) – Iterator

+0

+1 Ídem ....... – Andrie

+0

+1, ya que está utilizando la advertencia interna de R y los trucos de error. Puedo cortar el estado de salida del mensaje de advertencia. Sé que puedo usar stdout = TRUE, pero el estado de salida es mi principal preocupación. Es por eso que no hice eso. –

4

sugiere emplear esta función aquí:

robust.system <- function (cmd) { 
    stderrFile = tempfile(pattern="R_robust.system_stderr", fileext=as.character(Sys.getpid())) 
    stdoutFile = tempfile(pattern="R_robust.system_stdout", fileext=as.character(Sys.getpid())) 

    retval = list() 
    retval$exitStatus = system(paste0(cmd, " 2> ", shQuote(stderrFile), " > ", shQuote(stdoutFile))) 
    retval$stdout = readLines(stdoutFile) 
    retval$stderr = readLines(stderrFile) 

    unlink(c(stdoutFile, stderrFile)) 
    return(retval) 
} 

Esto sólo funcionará en una cáscara de Unix que acepta notaciones> y 2>, y el argumento cmd no debe redirigir el resultado. Pero hace el truco:

> robust.system("ls -la") 
$exitStatus 
[1] 0 

$stdout 
[1] "total 160"              
[2] "drwxr-xr-x 14 asieira staff 476 10 Jun 18:18 ."    
[3] "drwxr-xr-x 12 asieira staff 408 9 Jun 20:13 .."   
[4] "-rw-r--r-- 1 asieira staff 6736 5 Jun 19:32 .Rapp.history" 
[5] "-rw-r--r-- 1 asieira staff 19109 11 Jun 20:44 .Rhistory"  

$stderr 
character(0) 
Cuestiones relacionadas