5

IINM my system is failing when bashing

for i in {0..10000000}; #   Seven zeroes.
do
    false;
done #   `bash` exited and its `tmux` pane/window was closed.

or

for i in $(seq 0 10000000); #   Seven zeroes.
do
    false;
done #   `bash` exited and its `tmux` pane/window was closed.

but not when

for i in {0..1000000}; #   Six zeroes.
do
    false;
done #   Finished correctly.

Can you please briefly explain the internals of this behavior and prompt a workaround for getting the task done?

2
  • 2
    For you my all loved XY friends, a big file with CRLFs only is what I am actually trying to get.
    – 41754
    Commented Aug 27, 2014 at 12:28
  • Testing nl with lines alot, tabs and XY pow are what I got.
    – 41754
    Commented Aug 27, 2014 at 12:48

2 Answers 2

11
+50

for i in {0..1000000} and for i in $(seq 1000000) both build up a big list and then loop over it. That's inefficient and uses a lot of memory.

Use:

for ((i = 0; i<= 1000000; i++))

instead. Or POSIXly:

i=0; while [ "$i" -le 1000000 ]; do
  ...
  i=$(($i + 1))
done

Or:

seq 1000000 | xargs...

To get a file full of CRLFs:

yes $'\r' | head -n 1000000 >  file

Generally, loops should be avoided when possible in shells.

4
  • 1
    there's also the old /dev/zero/ thing... like tr \\0 \\r </dev/zero | tee - - - | dd or head or whatever... It might be better to mount a tmpfs of that size and fill it then cp to a file. Maybe not...
    – mikeserv
    Commented Aug 27, 2014 at 12:35
  • 3
    @mikeserv, yes Pourquoi faire simple quand on peut faire compliqué ? like they say in France. Commented Aug 27, 2014 at 12:38
  • dang man. you really are a funny guy sometimes. now I have to translate that... ahh. the double entendre. that's probably French too. and, yeah, I dunno why I do. but I do.
    – mikeserv
    Commented Aug 27, 2014 at 12:39
  • Telling you to work a pearl for it.
    – 41754
    Commented Aug 27, 2014 at 12:41
1

@Stéphane Chazelas gave a great answer up there.

Mine is not an answer. I just it got curious about the efficiency of the different solutions, so I thought I should share my results...

~# i=0 ; time while [ "$i" -le 1000000 ]; do ((i++)) ;done
real    0m21.753s

~# time for ((i = 0; i<= 1000000; i++))  ;do : ;done
real    0m15.791s

~# time for i in {0..1000000} ;do : ;done
real    0m8.897s

~# time for i in $(seq 0 1000000) ;do : ;done
real    0m7.760s

:~# time seq 1000000 | xargs true
real    0m0.938s

~# time yes $'\r' | head -n 1000000 >/dev/null
real    0m0.048s

The yes answer is the clear winner. :-) Besides, it actually does the work that the OP needed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .