Avoid the 'seq' command in Bash?
Asked Answered
W

1

1

I'm having a discussion about the use of seq for small loop in a Bash script (for example a loop with 10 iterations). I say, for example, is better do this

for i in {1..10}
do
   echo "Welcome $i times"
done

than use seq

for i in $(seq 10)
do
   echo "Welcome $i times"
done

as written here: http://www.cyberciti.biz/faq/bash-for-loop/

In my opinion is useless for short loop use a not a built-in command. What about performance for example?

Wolfgram answered 3/2, 2015 at 13:50 Comment(0)
U
5

seq comes handy when you do not know the range you are about to perform: you can say seq $a $b, whereas you cannot say {$a..$b}.

Also, {} is available just for Bash, so in for example Shell you won't be able to use it.

That being said, if you are targeting bash then using {1..10} is certainly going to be faster (and cheaper) than using seq and that can matter. seq is an external command, and that makes the execution slower.

From man bash:

Brace Expansion

Brace expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result. It is strictly textual. Bash does not apply any syntactic interpretation to the context of the expansion or the text between the braces.

...

Brace expansion introduces a slight incompatibility with historical versions of sh. sh does not treat opening or closing braces specially when they appear as part of a word, and preserves them in the output. Bash removes braces from words as a consequence of brace expansion. For example, a word entered to sh as file{1,2} appears identically in the output. The same word is output as file1 file2 after expansion by bash. If strict compatibility with sh is desired, start bash with the +B option or disable brace expansion with the +B option to the set command.

Unscramble answered 3/2, 2015 at 13:52 Comment(8)
That being said if you are targeting bash then using {1..10} is certainly going to be faster (and cheaper) than using seq and that can matter.Snodgrass
You nailed it, @EtanReisner, I just appended your comment to the answer :)Unscramble
So better to do for ((n=1; n<=10; n++)) ? And so the problem could be with a large loop, not short ?Wolfgram
@Wolfgram no, use {a..b} whenever it is possible. The problem could be if your range is not fixed; then, you cannot use {..} because it does not admit variables.Unscramble
Ok so the better solution is the first that I write, but if you don't know the range of a loop, you have to use seq. Is there other solution instead of seq ? What is your favourite?Wolfgram
@Wolfgram Yep! I don't like the for syntax in Bash, I find seq quite easier to write, so this is the one I use. And of course {a..b} if I know a and b beforehand :)Unscramble
I post this question because in the link I putted, below the seq example, you can read: There is no good reason to use an external command such as seq to count and increment numbers in the for loop, hence it is recommend that you avoid using seq. The builtin command are fast.Wolfgram
@Wolfgram Yes, this is true. So my usage of seq over for is bad in terms of performance. It would be best to use for ((n=$a; n<=$b; n++)) instead of seq $a $b. This is because, as you note from the link, executing a builtin is faster than calling an external command. However, as always it is good to check when to worry a lot about performance and when it is just a matter of characters you want to type in your script.Unscramble

© 2022 - 2024 — McMap. All rights reserved.