1

I run a program multible time using a bash script, and I want it's output to be written in a file. However, I couldn't make the operator ">filename.txt" work... Here is my script:

for i in {1..10000000..10000}
do
    time ./merge $i>nn
done

can somebody help me out?

Update:

The answer is:

{ time ./merge $i ; } 2>> time.txt
muru
  • 193,181
  • 53
  • 473
  • 722
Jim Blum
  • 1,407
  • 4
  • 19
  • 24

4 Answers4

3

time is a bit funny. It's a Bash built-in so the first thing you need to do is limit it to the right command. You can do that by grouping it with braces or subshelling with parenthesis.

Then you need to note that it outputs to STDERR. This won't be redirected by default but we can fix this by redirecting STDERR into STDOUT and then redirecting that.

Finally (as choroba spotted before me) using > will overwrite by default. Doing it in a loop will result in just the last iteration showing in the file. You want >> which will append.

{ time ./merge $i ; } >> nn 2>&1

If you don't want any original STDOUT, and just want the time output, you could run this instead:

{ time ./merge $i >/dev/null 2>&1; } 2>> nn

This is junking all the output of the ./merge command and is just redirecting the STDERR from the wider block.


Just as a test harness to show this working:

$ for i in {1..10}; do { time echo $i >/dev/null 2>&1; } 2>> nn ; done
$ wc -l nn
40 nn

That's 10×4-line time blocks (the echo output is suppressed).

Oli
  • 289,791
  • 117
  • 680
  • 835
  • Thanks a lot. I have replaced the command time ./merge $i>nn with the command you provided above, but still, I get time printed at my terminal... – Jim Blum Jun 27 '14 at 09:30
  • Maybe the redirection needs to happen within the braces... Try the edit. – Oli Jun 27 '14 at 09:32
  • No, still it doesn't work... – Jim Blum Jun 27 '14 at 09:33
  • I'm just an idiot. Position matters. The edited version should work. I tested it this time. – Oli Jun 27 '14 at 09:34
  • Thanks a lot Oli. Unfortunately, it still does not work for me... – Jim Blum Jun 27 '14 at 09:37
  • Is it possible that merge takes the "2>&1 ; } >> nn" as parameters as well? – Jim Blum Jun 27 '14 at 09:38
  • No, they should all be eaten by the shell. You can check $@ from within the script though. I've been testing this with `ls` as my command and it's worked fine so far. What are you seeing? – Oli Jun 27 '14 at 09:41
  • This is the answer, and the command I use now { time ./merge $i ; } 2>> time.txt – Jim Blum Jun 27 '14 at 09:52
1

You are overwriting the file in every iteration of the loop. Either, redirect the whole loop to the file

for i in {1..10000000..10000}
do
    time ./merge $i
done > nn

or, use append:

for i in {1..10000000..10000}
do
    time ./merge $i >> nn
done
choroba
  • 9,273
  • 1
  • 30
  • 42
  • Thanks a lot choroba. However, the problem is not the append (I had also tried that before). I still get the outputs of the time command at my terminal... – Jim Blum Jun 27 '14 at 09:31
  • This is better approach in my opinion. Instead of redirecting each iteration, this answer properly shows redirecting whole loop. +1 for that. As for `time` output, it needs to be grouped either via curly brackets to run as list in current shell or parenthesis to run in subshell. And it writes to stderr, hence it must use &> redirection to include stderr stream into output file – Sergiy Kolodyazhnyy May 29 '17 at 21:28
1

time prints its results to standar error, not standard output. You therefore need to redirect the former with 2> instead of the latter with >. Your next issue is that you are capturing the output of ./merge and not of time. So, you need to group the time and ./merge commands and then redirect their output. This can be done either by running them in a separate subshell or by grouping them in the current shell:

  1. Run in a separate subshell

    for i in {1..10000000..10000}
    do
      ( time ./merge $i ) 2>> nn
    done
    
  2. Run in the same shell

    for i in {1..10000000..10000}
    do
      { time ./merge $i; } 2>> nn
    done
    

In this particular case, there is no practical difference between the two approaches.

terdon
  • 98,183
  • 15
  • 197
  • 293
1

The bash intrinsic time is not the same as /usr/bin/time. The latter will allow you to append to a file:

/usr/bin/time --append --outout=outputfile command
Jack
  • 11
  • 1
  • 1
    OK, but bash's `time` looks different from what `/usr/bin/time` shows by default, so suggestion - use `-p` flag with `/usr/bin/time` to make it look the same – Sergiy Kolodyazhnyy May 29 '17 at 22:05