How to zero-pad numeric variables in zsh (and maybe also bash?)
Asked Answered
H

6

34

In zsh, when I have to create a bunch of files with zsh, I usually do something like:

for x in $(seq 1 1000); do .....; done

This works fine, it gives me files with names foo-1.txt .. foo-1000.txt.
However, these files do not sort nicely, so I would like to zero-pad the $x variable, thus producing names of foo-0001.txt .. foo-1000.txt.

How to do that in zsh? (and bonus question, how to do it in bash?)

Huarache answered 15/3, 2012 at 8:17 Comment(0)
M
19

Use the -w flag to seq (in any shell):

$ seq -w 1 10
01
02
03
04
05
06
07
08
09
10
Maytime answered 15/3, 2012 at 8:22 Comment(1)
seq -w 001 005 # padsGalenic
M
37

For reference sake, if you do not have control over the generation of the numeric values, you can do padding with:

% value=314
% echo ${(l:10::0:)value}
0000000314
% echo $value
314
Margheritamargi answered 15/4, 2013 at 14:26 Comment(5)
Seeing that ${(l... is not very search-engine friendly, look this up under Parameter Expansion Flags in zshexpn(1). Also paired delimiters can be used to make the syntax a bit more intuitive: ${(l{10}{0})value}.Pulp
Strangely, zmv doesn’t understand that form, though parentheses work fine: ${(l(10)(0))value}.Pulp
echo ${(l:3::0:)$((++value))}Galenic
a strange caveat: if the value is longer than the given length the first digits are cut of, e.g. for l=3 and a value of 1234 the output is 234.Coral
This needs an explanation edited into the answer. Only the 10 and the value are intuitive.Fu
M
19

Use the -w flag to seq (in any shell):

$ seq -w 1 10
01
02
03
04
05
06
07
08
09
10
Maytime answered 15/3, 2012 at 8:22 Comment(1)
seq -w 001 005 # padsGalenic
O
12

You can use bash's brace expansion:

$ for n in file-{0001..1000}.txt; do echo $n; done
file-0001.txt
file-0002.txt
file-0003.txt
file-0004.txt
file-0005.txt
file-0006.txt
file-0007.txt
file-0008.txt
file-0009.txt
file-0010.txt
...
file-0998.txt
file-0999.txt
file-1000.txt

Works in zsh too.

Ocular answered 15/3, 2012 at 11:16 Comment(0)
I
10

in Zsh:

% my_num=43
% echo ${(l(5)(0))my_num}
00043
Ignominious answered 10/2, 2020 at 18:19 Comment(0)
L
3

Works in bash (don't know for zsh):

echo foo{0000..1000}.txt 
Lantern answered 15/3, 2012 at 11:17 Comment(2)
echo foo{0000..1000}.txt for zshWien
Thanks, @olejorgenb, it is {a..z} and not {a-z} in bash as well. A-Z is used in file globbing like ls [0-1]000.txt for example. Over 10 years nobody complained!Lantern
A
1
  1. printf
    Using printf to pad with zeros works in any shell:

    $ printf 'foo%03d.txt\n' $(seq 4)
    foo001.txt
    foo002.txt
    foo003.txt
    foo004.txt
    
    $           printf  'foo%03d.txt\n' {1..4}       # works in bash, ksh, zsh.
    $ n=4;      printf  'foo%03d.txt\n' {1..$n}      # only ksh, zsh
    $ n=4; eval printf '"foo%03d.txt\n" {1..'"$n"'}' # workaround needed for bash
    
  2. Use brace expansion (only bash and zsh keep the leading zeros ksh don't).

    $ printf '%s\n' foo{1..004}.txt
    foo001.txt
    foo002.txt
    foo003.txt
    foo004.txt
    
Azotize answered 9/6, 2017 at 7:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.