/usr/bin/time giving its output in one single line - bash

I may have a locale problem or something similar, because whenever I run /usr/bin/time it gives me the output as a single line, difficult to interpret :
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 1756maxresident)k
The above comes from echo with no parameters, but it's the case with all commands.

try to use the 'POSIX' style:
$ /usr/bin/time -p ls
or integrated time in bash/zsh/fish...
$ time ls
or use your style, by creating a var called TIME or in some system called TIMEFORMAT
$ export TIME="%E"
$ /usr/bin/time ls

Related

Suppress output of a command while recording output from "time"

I have some command which launches in this way:
./mycommand -arg=word
I measure execution time and write output to file:
/usr/bin/time -f "%K %e" ./mycommand -arg=word 2>file
However, mycommand has also stderr output. So file contains mixed data from both (time and mycommand). How can I suppress mycommand output and save time data?
If the nature of your process is such that a shell startup won't interfere with the timing too much, one simple approach is to have a shell run the direction as a subprocess of time:
/usr/bin/time -f "%K %e" sh -c '"$0" "$#" >/dev/null 2>&1' ./mycommand -arg=word
I would also suggest using the bash-builtin version of time instead of the external one, which lets you use tricks documented in BashFAQ #32:
TIMEFORMAT='%R' # replace for whatever is equivalent to your "%K %e"
timing=$(time { ./mycommand >/dev/null 2>&1; } 2>&1)

Writing a script that runs a command and times it

I'm trying to write a script that will run and time a given and output that to a file in a .csv format.
So far from looking at SO previous posts, I've found that sh -c "$index_of_command_arg" can be used to invoke that command.
I'm also familiar with time and I know that people use /usr/bin/time for formatting, but I need to format the time given in total seconds (for example, 1.34516) but the only given option to format the real time is %E which return [hours:]minutes:seconds. Is there any way to format it the way I need?
The general idea of my script is:
# ----
# some input validation
# ----
rule=$1
command=$2
execution_time=/usr/bin/time -f "%total_seconds" sh -c "$command" #is this line possible?
echo "$rule,$execution_time" > output_file.csv
Can this be formatted the way I want? and also, the line with the comment after it,
Will this even work the way I wrote it? is the syntax correct?
Say I use the normal time and I get the real 0m2.003 ...
output, how can I take the 2.003 out of it?
The normal time you are mentioning is the bash built-in time. From the Bash Reference Manual:
The TIMEFORMAT variable may be set to a format string
that specifies how the timing information should be displayed.
…
%[p][l]R
The elapsed time in seconds.
So, you could use
execution_time=`TIMEFORMAT=%R bash -c "time $command" 2>&1 >/dev/tty`
You replace:
execution_time=/usr/bin/time -f "%total_seconds" sh -c "$command" `
with:
execution_time=`(time sh -c "$command > /dev/null 2>&1") 2>&1 | grep real |sed "s/.*m//;s/s.*//;"`
or with:
execution_time=`(time sh -c "$command > /dev/null 2>&1") 2>&1 | grep real | cut -c 8-12`
Why > /dev/null - you don't want to see $command output 2>&1 (STDERR > STDOUT)
Why 2>&1 for time command (for the same reason as in previous bullet)

how to use GNU Time with pipeline

I want to measure the running time of some SQL query in postgresql. Using BASH built-in time, I could do the following:
$ time (echo "SELECT * FROM sometable" | psql)
I like GNU time, which provides more formats. However I don't know how to do it with pipe line. For simplicity, I use ls | wc in the following examples:
$ /usr/bin/time -f "%es" (ls | wc)
-bash: syntax error near unexpected token `('
$ /usr/bin/time -f "%es" "ls | wc"
/usr/bin/time: cannot run ls | wc: No such file or directory
If I do not group the pipe in any way, it does not complains:
$ /usr/bin/time -f "%es" ls | wc
0.00s
But apparently, this only measure the first part of the pipe, as showing in the next example
$ /usr/bin/time -f "%es" ls | sleep 20
0.00s
So the question is what is the correct syntax for GNU Time with pipe line?
Call the shell from time:
/usr/bin/time -f "%es" bash -c "ls | wc"
Of course, this will include the shell start-up time as well; it shouldn't be too much, but if you're on a system that has a lightweight shell like dash (and it's sufficient to do what you need), then you could use that to minimize the start-up time overhead:
/usr/bin/time -f "%es" dash -c "ls | wc"
Another option would be to just time the command you are actually interested in, which is the psql command. time will pass its standard input to the program being executed, so you can run it on just one component of the pipeline:
echo "SELECT * FROM sometable" | /usr/bin/time -f "%es" psql
Create a script that calls your pipeline. Then
/usr/bin/time -f '%es' script.sh

Why a command option "-f" be taken as a command by bash

I run the command copied from the time's manual, but it complained -f command not found. Why it recognized -f as a command?
$ time -f "%E real,%U user,%s sys" ls -Fs
-f: command not found
real 0m0.152s
user 0m0.108s
sys 0m0.040s
I doubt the shell and decide to try another shell. In the above, the shell is bash. I switched to dash and found time run correctly now.
My system is Linux Mint 13.
time is a built-in command in bash and zsh. If you'd like to execute the external command instead, you should call /usr/bin/time -f ....
You can use the bash built-in command to suppress shell functions and built-ins:
command time -f "%E real,%U user,%s sys" ls -Fs
(Longer, but a little more explicit, than using \time.)
Bash includes a stripped-down version of time. Use /usr/bin/time instead.
Added to other answers, you can override the built-in command by \.
\time -f "%E real,%U user,%s sys" ls -Fs

How to time a vim session using 'time'

I'm trying to log the time I spend working in vim. I've got a script that works with gvim but when I try to set it up with vim it locks up the terminal session silently or with the message 'Vim: Warning: Output is not to a terminal'
Here is the script that works with gvim:
#!/bin/sh
workfile="/home/na/writing/fiction.txt"
worklog="/home/na/writing/worktime.log"
d=`date --rfc-3339 date`
t=$( { /usr/bin/time -f "%e" /usr/local/bin/gvim -f -S /home/na/.vim/writeroom/writeroom.vim $workfile; } 2>&1 )
w=`wc -w $workfile`
echo $d $t $w >> $worklog
When I close the gvim window I get a logfile containing a date, the number of seconds I spent editing the file, and a word count for the file.
2011-08-15 700.15 238869 /home/na/writing/fiction.txt
I would like the same using vim in a terminal session.
I understand vim talks to the terminal directly instead of to stdout but I don't care about what vim returns, I want the output from the time command.
These don't work:
t=`/usr/bin/time -f "%e" /usr/local/bin/vim -f $workfile`
t=$( { /usr/bin/time -f "%e" /usr/local/bin/vim -f $workfile; } 2>&1 )
t=$( { /usr/bin/time -f "%e" /usr/local/bin/vim -f $workfile; } )
I suspect there's some combination of backticks and paranthesis that will make this work but I haven't stumbled onto it yet.
The backtick or $() operators capture vim's output (what you see on the terminal when opening vim is vim's output from its stdout), so you can't do that.
You could try this instead:
start=$(date +%s)
/usr/local/bin/vim -f $workfile
end=$(date +%s)
duration=$((end-start))
echo "$duration"
Some versions of time (eg: GNU's) support a flag to set the output file. eg:
/usr/bin/time -o /tmp/foo vim
If you're using bash you'll need to use the path for time (or a leading \) as bash has a reserved word time which behaves similar to the time command (but operates on an entire pipeline) that does not support the -o flag.

Resources