¿Redirigir la salida del comando de tiempo en unix a una variable en bash?

13

Solo quiero capturar la salida de un comando de tiempo, es decir:

X=$(time ls)

o

$(time ls) | grep real

Sin embargo, la función de tiempo lo escupe a la consola. ¿Cómo hago esto?

Joshua Enfield
fuente

Respuestas:

12

X = `(tiempo ls) 2> & 1 | grep real`

Jason Berg
fuente
No necesita una subshell solo para time; La respuesta de Dennis Williamson es mejor en ese sentido.
musiphil
11

Ver BashFAQ / 032 .

$ # captures output of command and time
$ time=$( TIMEFORMAT="%R"; { time ls; } 2>&1 )    # note the curly braces

$ # captures the time only, passes stdout through
$ exec 3>&1 4>&2
$ time=$(TIMEFORMAT="%R"; { time ls 1>&3 2>&4; } 2>&1)
bar baz
$ exec 3>&- 4>&-

El tiempo se verá como "0.000" usando TIMEFORMAT="%R"cuál será el tiempo "real".

Pausado hasta nuevo aviso.
fuente
¿podrías explicar un poco cómo funciona esto? He usado un fragmento como este estilo de culto de carga durante años. ¿Cuál es la secuencia 3 y 4? y el '-' ?
Sirex
1
@Sirex: las secuencias 3 y 4 son secuencias creadas por el execcomando en mi respuesta utilizando los descriptores de archivo disponibles. Cualquier descriptor de archivo disponible podría ser utilizado. Las secuencias 3 y 4 son copias de 1 ( stdout) y 2 ( stderr), respectivamente. Esto permite la salida de lspasar normalmente a stdouty stderra través de 3 y 4 mientras que la salida de time(que normalmente va a stderr) se redirige a la original stdout(1) y, a continuación capturada en la variable mediante la sustitución de comandos. Como puede ver en mi ejemplo, los nombres de los archivos bary bazse envían al terminal. ...
Pausado hasta nuevo aviso.
1
... Una vez finalizado, las secuencias adicionales se cierran utilizando el seguimiento -.
Pausado hasta nuevo aviso.
4

Time escribe su salida en STDERR en lugar de STDOUT. Para empeorar las cosas, por defecto 'time' es un comando integrado de shell, por lo que si intenta 'time ls 2> & 1', '2> & 1' solo se aplica a 'ls'.

La solución probablemente sería algo como:

/usr/bin/time -f 'real %e' -o OUTPUT_FILE ls > /dev/null 2>&1<br>
REALTIME=$(cat OUTPUT_FILE | cut -f 2 -d ' ')

Hay formas más elegantes de hacerlo, pero esa es la forma clara / simple.

Jason
fuente
Estoy interesado en hacer esto sin -o. ¿Puedes publicar uno de los elegantes métodos en los que estabas pensando :)?
David Doria
0

La respuesta de @Dennis Williamson es excelente, pero no le ayuda a almacenar la salida del comando en una variable y la salida de timeotra variable. En realidad, esto no es posible utilizando descriptores de archivo.

Si desea registrar cuánto tiempo tarda un programa en ejecutarse, puede hacerlo simplemente restando la hora de inicio de la hora de finalización. Aquí hay un ejemplo simple que muestra cuántos milisegundos tardó un programa en ejecutarse:

START_TIME=$(date +%s%3N)
OUTPUT=$(ls -l)
ELAPSED_TIME=$(expr $(date +%s%3N) - $START_TIME)
echo "Command finished in $ELAPSED_TIME milliseconds"

Esto no es tan preciso como el timecomando, pero debería funcionar perfectamente para la mayoría de los scripts de bash.

Lamentablemente, el datecomando de Mac no admite el %Nformato, pero puede instalar coreutils( brew install coreutils) y usar gdate:

START_TIME=$(gdate +%s%3N)
OUTPUT=$(ls -l)
ELAPSED_TIME=$(expr $(gdate +%s%3N) - $START_TIME)
echo "Command finished in $ELAPSED_TIME milliseconds"
ndbroadbent
fuente