2

for ((i=000;i<040;i++));do ...

From 0 to 39, there is 40 values!? ... for printing from A to Z???

for ((i=000;i<040;i++));do
    printf %b "$(printf \\%03o\  $((65+0$i)))"
  done 2>/dev/null |
  xargs
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

strange!?

There is 85 values, from 70 to 154:

for ((i=0070;i<0155;i++));do
    printf %b "$(printf \\%03o\  $((19+0$i)))"
  done 2>/dev/null |
    xargs
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

😜 Dummy request (about error handling)! Don't re-open this!! ;-p

Answer

As this question was closed, no answer could be added, so there is my explanation:

The missunderstanding is done by the (ab)use of 2>/dev/null!!

So, simply dropping this will output:

for ((i=000;i<040;i++));do
    echo -e $(eval "printf "\\\\%04o" $((65+0$i)) ")
done  |   xargs
bash: 65+08: value too great for base (error token is "08")
bash: 65+09: value too great for base (error token is "09")
bash: 65+018: value too great for base (error token is "018")
bash: 65+019: value too great for base (error token is "019")
bash: 65+028: value too great for base (error token is "028")
bash: 65+029: value too great for base (error token is "029")
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

Things become more clear!!

We could count error lines by using wc -l:

for ((i=000;i<040;i++));do
    echo -e $(eval "printf "\\\\%04o" $((65+0$i)) ")
done 2> >(wc -l >&2) |   xargs
6
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

There are 6 error lines, because of illegal digit 8 or 9 in octal numbers.

So if this is octal, then you could either

printf %d\\n 040

or

echo $(( 040 ))

or

echo $(( 8#40 ))

to convert 040 octal to 32 decimal (4 * 8 + 0 = 32).

Then having 32 operation with 6 errors dropped, there are finally 26 outputs.

With wc -l again:

for ((i=0070;i<0155;i++));do
    echo -e $(eval "printf "\\\\%04o" $((19+0$i)) ")
  done 2> >(wc -l >&2) | xargs 
27
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

There are in fact 27 errors, with values from...

printf "%d\n" 0070 0155
56
109

From 56 to 108! There is not 85 values, but 53!!

echo $(( 155 - 70 ))  $(( 0155 - 070 ))  $(( 109 - 56 ))
85 53 53

Again: 53 operations with 27 errors = 26 outputs

echo $((53-27))
26

Yes!

This is the right number of letters (in the alphabet I know)!

Conclusion

The question could be rewritten as:

How abuse of /dev/null could make strange behaviours

So be carefull when redirecting STDERR! Avoid simply redirecting STDERR to /dev/null:

command 2>/dev/null

And prefer to use commands like:

command 2> >(grep -v "unwanted message" >&2)
10
  • 3
    There are 40 steps. Not 41.
    – Natan Cox
    Commented Jan 20, 2013 at 10:09
  • Hi, @F.Hauri 0-39, including 0; 40 is not there, buddy. i<040 right?
    – Kent
    Commented Jan 20, 2013 at 10:18
  • 2
    @F.Hauri So if you know that, why do you ask the question?
    – Macmade
    Commented Jan 20, 2013 at 10:23
  • 1
    @F.Hauri Ok, removed my down-vote for the effort of maintaining your post and trying to add context... : )
    – Macmade
    Commented Dec 10, 2013 at 20:39
  • 1
    @Macmade Thanks, the original meaning of this was about /dev/null abuse... I think, this is strongly linked to a lot of question about redirections, STDERR / STDIN and may concern beginers: ( First step in debugging: remove /dev/null ;-) Commented Dec 10, 2013 at 20:51

3 Answers 3

6

You are simply using octal numbers, as your numbers are prefixed by 0.

So it's base 8, not base 10.

6

You have 31 steps because 040 is octal for decimal 32.

Octal is a numeral system with the base 8. Decimal has the base 10 and hexadecimal 16.

4
  • This is not true. I mean the 1st sentence.
    – Kent
    Commented Jan 20, 2013 at 10:19
  • You may try for ((i=000;i<=040;i++));do.
    – rekire
    Commented Jan 20, 2013 at 10:21
  • +1 ah... bash! I was under zsh......!
    – Kent
    Commented Jan 20, 2013 at 10:26
  • At all, 31 step for my alphabet is too much! ;-) Commented Jan 20, 2013 at 10:49
1

Why don't you just use the following to print the alphabet?

for letter in {A..Z} ; do
    echo $letter
done  

Not the answer you're looking for? Browse other questions tagged or ask your own question.