Redirecionar a saída do comando time no unix para uma variável no bash?

13

Eu só quero capturar a saída de um comando de tempo, ou seja:

X=$(time ls)

ou

$(time ls) | grep real

A função time cospe-a no console. Como eu faço isso?

Joshua Enfield
fonte

Respostas:

12

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

Jason Berg
fonte
Você não precisa de um subshell apenas para time; A resposta de Dennis Williamson é melhor nesse sentido.
Musiphil
11

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

O tempo será semelhante a "0,000", usando o TIMEFORMAT="%R"qual será o tempo "real".

Pausado até novo aviso.
fonte
você poderia explicar um pouco como isso funciona? Eu uso um trecho como esse estilo de culto de carga há anos. O que é o stream 3 e 4? e a '-' ?
Sirex
1
@ Sirex: os fluxos 3 e 4 são fluxos criados pelo execcomando na minha resposta usando descritores de arquivos disponíveis. Qualquer descritor de arquivo disponível pode ser usado. Os fluxos 3 e 4 são cópias de 1 ( stdout) e 2 ( stderr), respectivamente. Isso permite que a saída lspasse normalmente para stdoute stderrvia 3 e 4 enquanto a saída de time(que normalmente vai para stderr) é redirecionada para o original stdout(1) e depois capturada na variável usando substituição de comando. Como você pode ver no meu exemplo, os nomes de arquivos bare bazsão enviados para o terminal. ...
Pausado até novo aviso.
1
... Depois de finalizados, os fluxos extras são fechados usando o final -.
Pausado até novo aviso.
4

O tempo grava sua saída em STDERR em vez de STDOUT. Para piorar a situação, por padrão 'time' é um comando interno do shell; portanto, se você tentar 'time ls 2> & 1', o '2> & 1' se aplicará apenas a 'ls'.

A solução provavelmente seria 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 ' ')

Existem maneiras mais elegantes de fazer isso, mas essa é a maneira clara / simples.

Jason
fonte
Estou interessado em fazer isso sem -o. Você pode postar um dos métodos sofisticados em que estava pensando :)?
22414 David Doria
0

A resposta de @Dennis Williamson é ótima, mas não ajuda a armazenar a saída do comando em uma variável e a saída de timeem outra variável. Na verdade, isso não é possível usando descritores de arquivo.

Se você deseja registrar quanto tempo um programa leva para ser executado, você pode fazer isso subtraindo a hora de início da hora de término. Aqui está um exemplo simples que mostra quantos milissegundos um programa levou para executar:

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

Isso não é tão preciso quanto o timecomando, mas deve funcionar perfeitamente para a maioria dos scripts bash.

Infelizmente, o datecomando do Mac não suporta o %Nformato, mas você pode instalar coreutils( brew install coreutils) e 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
fonte