Перенаправить вывод команды времени в unix в переменную в bash?

13

Я просто хочу захватить вывод команды времени, т.е.

X=$(time ls)

или

$(time ls) | grep real

Хотя функция времени плюет на консоль. Как мне это сделать?

Джошуа Энфилд
источник

Ответы:

12

X = `(время лс) 2> & 1 | grep real`

Джейсон Берг
источник
Вам не нужна подоболочка только для time; Ответ Денниса Уильямсона лучше в этом отношении.
Musiphil
11

Смотрите 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>&-

Время будет выглядеть как «0,000», используя TIMEFORMAT="%R"реальное время.

Приостановлено до дальнейшего уведомления.
источник
Не могли бы вы немного объяснить, как это работает? Я использую фрагмент, подобный этому стилю грузового культа, годами. Что такое поток 3 и 4? и "-"?
Sirex
1
@Sirex: потоки 3 и 4 - это потоки, созданные execкомандой в моем ответе с использованием доступных файловых дескрипторов. Можно использовать любые доступные файловые дескрипторы. Потоки 3 и 4 являются копиями 1 ( stdout) и 2 ( stderr) соответственно. Это позволяет lsнормально передавать выходные данные в stdoutи stderrчерез 3 и 4, в то время как выходные данные time(которые обычно идут в stderr) перенаправляются в исходное состояние stdout(1) и затем записываются в переменную с помощью подстановки команд. Как вы можете видеть в моем примере, имена файлов barи bazвыводятся на терминал. ...
Приостановлено до дальнейшего уведомления.
1
... После завершения дополнительные потоки закрываются с помощью трейлинга -.
Приостановлено до дальнейшего уведомления.
4

Время записывает свой вывод в STDERR, а не в STDOUT. Что еще хуже, по умолчанию 'time' является встроенной командой оболочки, поэтому, если вы попытаетесь 'time ls 2> & 1', '2> & 1' будет применяться только к 'ls'.

Решение, вероятно, будет что-то вроде:

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

Есть более причудливые способы сделать это, но это ясный / простой способ.

Джейсон
источник
Я заинтересован в том, чтобы сделать это без -o. Можете ли вы опубликовать один из причудливых методов, о которых вы думали :)?
Дэвид Дория
0

Ответ @Dennis Williamson отличный, но он не поможет вам сохранить выходные данные команды в одной переменной, а выходные данные - timeв другой переменной. На самом деле это невозможно при использовании файловых дескрипторов.

Если вы хотите записать, сколько времени занимает запуск программы, вы можете сделать это, просто вычтя время начала из времени окончания. Вот простой пример, который показывает, сколько миллисекунд потребовалось программе для запуска:

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

Это не так точно, как timeкоманда, но она должна прекрасно работать для большинства скриптов bash.

К сожалению, dateкоманда Mac не поддерживает %Nформат, но вы можете установить coreutils( brew install coreutils) и использовать 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
источник