Rediriger la sortie de la commande time sous unix vers une variable dans bash?


13

Je veux juste capturer la sortie d'une commande de temps, c'est-à-dire:

X=$(time ls)

ou

$(time ls) | grep real

La fonction de temps le crache cependant à la console. Comment puis-je faire cela?

Réponses:


12

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


Vous n'avez pas besoin d'un sous-shell juste pour time; La réponse de Dennis Williamson est meilleure à cet égard.
musiphil

11

Voir 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>&-

L'heure ressemblera à "0,000" en utilisant TIMEFORMAT="%R"l'heure qui sera "réelle".


pourriez-vous expliquer un peu comment cela fonctionne? J'utilise un extrait comme ce style culte de la cargaison depuis des années. Quel est le flux 3 et 4? et le '-' ?
Sirex

1
@Sirex: Les flux 3 et 4 sont des flux créés par la execcommande dans ma réponse en utilisant les descripteurs de fichiers disponibles. Tous les descripteurs de fichiers disponibles peuvent être utilisés. Les flux 3 et 4 sont des copies de 1 ( stdout) et 2 ( stderr), respectivement. Cela permet à la sortie de lsde passer normalement vers stdoutet stderrvia 3 et 4 tandis que la sortie de time(qui va normalement vers stderr) est redirigée vers l'original stdout(1) puis capturée dans la variable à l'aide de la substitution de commande. Comme vous pouvez le voir dans mon exemple, les noms de fichiers baret bazsont sortis sur le terminal. ...
pause jusqu'à nouvel ordre.

1
... Une fois terminé, les flux supplémentaires sont fermés à l'aide de la fin -.
pause jusqu'à nouvel ordre.

4

Time écrit sa sortie dans STDERR plutôt que STDOUT. Pour aggraver les choses, par défaut 'time' est une commande intégrée au shell, donc si vous essayez 'time ls 2> & 1' le '2> & 1' ne s'applique qu'à 'ls'.

La solution serait probablement quelque chose comme:

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

Il existe des façons plus sophistiquées de le faire, mais c'est la manière claire / simple.


Je suis intéressé à le faire sans -o. Pouvez-vous publier l'une des méthodes sophistiquées auxquelles vous pensiez :)?
David Doria

0

La réponse de @Dennis Williamson est excellente, mais elle ne vous aide pas à stocker la sortie de la commande dans une variable et la sortie de timedans une autre variable. Ce n'est en fait pas possible en utilisant des descripteurs de fichiers.

Si vous souhaitez enregistrer la durée d'exécution d'un programme, vous pouvez le faire en soustrayant simplement l'heure de début de l'heure de fin. Voici un exemple simple qui montre combien de millisecondes un programme a pris pour s'exécuter:

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

Ce n'est pas aussi précis que la timecommande, mais cela devrait fonctionner parfaitement pour la plupart des scripts bash.

Malheureusement, la datecommande Mac ne prend pas en charge le %Nformat, mais vous pouvez installer coreutils( brew install coreutils) et utiliser gdate:

START_TIME=$(gdate +%s%3N)
OUTPUT=$(ls -l)
ELAPSED_TIME=$(expr $(gdate +%s%3N) - $START_TIME)
echo "Command finished in $ELAPSED_TIME milliseconds"
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.