Differences between revisions 1 and 3 (spanning 2 versions)
Revision 1 as of 2007-05-02 23:04:00
Size: 1899
Editor: redondos
Comment:
Revision 3 as of 2008-03-10 10:52:49
Size: 2625
Editor: 134
Comment: seq might be considered bad style
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:
Line 6: Line 7:
Line 12: Line 14:
Line 14: Line 15:
{{{
00
01
02
03
[...]
}}}

This gets tedious for large sequences, but there are other ways, too. If the command {{{seq}}} is available, you can use it as follows:
{{{
    seq -w 1 10
}}}

or, for arbitrary numbers of leading zeros (here: 3):
Line 30: Line 17:
    seq -f "%03g" 1 10    00
   01
   02
   03
   [...]
Line 32: Line 23:

If you have the {{{printf}}} command (which is a Bash builtin, and is also POSIX standard), it can be used to format a number, too:
This gets tedious for large sequences, but there are other ways, too. If you have the {{{printf}}} command (which is a Bash builtin, and is also POSIX standard), it can be used to format a number:
Line 36: Line 26:
    for ((i=1; i<=10; i++))     for ((i=1; i<=10; i++))     # Bash 2 for-loop syntax
Line 41: Line 31:
In Bash 3, you can use ranges inside brace expansion. Also, since {{{printf}}} will implicitly loop if given more arguments than format specifiers, you can simplify this enormously:
Line 42: Line 33:
{{{
   printf "%03d\n" {1..300} # Bash 3 brace expansion
}}}
Line 49: Line 43:
If the command {{{seq(1)}}} is available (it's part of GNU sh-utils/coreutils), you can use it as follows:

{{{
    seq -w 1 10
}}}
or, for arbitrary numbers of leading zeros (here: 3):

{{{
    seq -f "%03g" 1 10
}}}
Combining {{{printf}}} with {{{seq(1)}}}, you can do things like this:

{{{
   printf "%03d\n" $(seq 300)
}}}
(That may be helpful if your version of {{{seq(1)}}} lacks {{{printf}}}-style format specifiers. Since it's a nonstandard external tool, it's good to keep your options open.)

Be warned however that seq might be considered bad style, it's even mentioned in ["Don't Ever Do These"].
Line 53: Line 65:
i=0
while test $i -le 10
do
    echo "00$i"
    i=`expr $i + 1`
done |
    sed 's/.*\(...\)$/\1/g'
   i=0
   while test $i -le 10
   do
    echo "00$i"
       i=`expr $i + 1`
   done |
    sed 's/.*\(...\)$/\1/g'
Line 61: Line 73:
In this example, the number of '.' inside the parentheses in the {{{sed}}} command determines how many total bytes from the {{{echo}}} command (at the end of each line) will be kept and printed.
Line 62: Line 75:
In this example, the number of '.' inside the parentheses in the {{{sed}}} statement determins how many total bytes from the {{{echo}}} command (at the end of each line) will be kept and printed.

One more addendum: in Bash 3, you can use:
{{{
printf "%03d \n" {1..300}
}}}

Which is slightly easier in some cases.

Also you can use the {{{printf}}} command with xargs and wget to fetch files:
Now, since the number one reason this question is asked is for downloading images in bulk, you can use the {{{printf}}} command with {{{xargs(1)}}} and {{{wget(1)}}} to fetch files:
Line 74: Line 78:
printf "%03d \n" {$START..$END} | xargs -i% wget $LOCATION/%    printf "%03d\n" {$START..$END} | xargs -i% wget $LOCATION/%
Line 76: Line 80:

Sometimes a good solution.

I found that on bash 2 you can nest seq in back ticks and this will work as well.
Or, in a slightly more general case:
Line 82: Line 83:
printf "%03d \n" `seq 300`    for i in {1..100}; do
      wget "$prefix$(printf %03d $i).jpg"
      # other commands
   done

Anchor(faq18)

How can I use numbers with leading zeros in a loop, e.g. 01, 02?

As always, there are different ways to solve the problem, each with its own advantages and disadvantages.

If there are not many numbers, BraceExpansion can be used:

    for i in 0{1,2,3,4,5,6,7,8,9} 10
    do
        echo $i
    done

Output:

   00
   01
   02
   03
   [...]

This gets tedious for large sequences, but there are other ways, too. If you have the printf command (which is a Bash builtin, and is also POSIX standard), it can be used to format a number:

    for ((i=1; i<=10; i++))     # Bash 2 for-loop syntax
    do
        printf "%02d " "$i"
    done

In Bash 3, you can use ranges inside brace expansion. Also, since printf will implicitly loop if given more arguments than format specifiers, you can simplify this enormously:

   printf "%03d\n" {1..300}     # Bash 3 brace expansion

The KornShell and KornShell93 have the typeset command to specify the number of leading zeros:

    $ typeset -Z3 i=4
    $ echo $i
    004

If the command seq(1) is available (it's part of GNU sh-utils/coreutils), you can use it as follows:

    seq -w 1 10

or, for arbitrary numbers of leading zeros (here: 3):

    seq -f "%03g" 1 10

Combining printf with seq(1), you can do things like this:

   printf "%03d\n" $(seq 300)

(That may be helpful if your version of seq(1) lacks printf-style format specifiers. Since it's a nonstandard external tool, it's good to keep your options open.)

Be warned however that seq might be considered bad style, it's even mentioned in ["Don't Ever Do These"].

Finally, the following example works with any BourneShell derived shell to zero-pad each line to three bytes:

   i=0
   while test $i -le 10
   do
       echo "00$i"
       i=`expr $i + 1`
   done |
       sed 's/.*\(...\)$/\1/g'

In this example, the number of '.' inside the parentheses in the sed command determines how many total bytes from the echo command (at the end of each line) will be kept and printed.

Now, since the number one reason this question is asked is for downloading images in bulk, you can use the printf command with xargs(1) and wget(1) to fetch files:

   printf "%03d\n" {$START..$END} | xargs -i% wget $LOCATION/%

Or, in a slightly more general case:

   for i in {1..100}; do
      wget "$prefix$(printf %03d $i).jpg"
      # other commands
   done

BashFAQ/018 (last edited 2019-08-21 16:24:29 by GreyCat)