Q: Expandig curly braces with `bash` There is a lot of documentation about this online, and the bash man page is really nice.
Even so, I can't understand why this is not working.
Obviously I'm missing something...
I have a directory with 100 files, named file010, file020 ... file1000.
I want them renamed to new00..99 using mv (well, mvg actually, buth both have the same output).
When I run any of the following, I get target 'new99' is not a directory (always the last).
What am I missing?
id@machine  ~/temp/test  ls
file010  file090   file160  file240  file320  file400  file480  file560  file640  file720  file800  file880  file960
file020  file100   file170  file250  file330  file410  file490  file570  file650  file730  file810  file890  file970
file030  file1000  file180  file260  file340  file420  file500  file580  file660  file740  file820  file900  file980
file040  file110   file190  file270  file350  file430  file510  file590  file670  file750  file830  file910  file990
file050  file120   file200  file280  file360  file440  file520  file600  file680  file760  file840  file920
file060  file130   file210  file290  file370  file450  file530  file610  file690  file770  file850  file930
file070  file140   file220  file300  file380  file460  file540  file620  file700  file780  file860  file940
file080  file150   file230  file310  file390  file470  file550  file630  file710  file790  file870  file950
 id@machine  ~/temp/test  mv {*,new{00..99}}
/usr/local/bin/mvg: target 'new99' is not a directory
 ✘ id@machine  ~/temp/test  mv {file{010..1000..10},new{00..99}}
/usr/local/bin/mvg: target 'new99' is not a directory
 ✘ id@machine  ~/temp/test  mv {file*,new{00..99}}
/usr/local/bin/mvg: target 'new99' is not a directory


A: What are you missing? How mv works.
When you provide exactly 2 files, you are renaming the first filename to become the second filename.
With more than 2 files, the last argument is taken as a directory, and all previous arguments are files to be moved there.
Refer to the man page.
To rename your files, you need a loop:
i=0
for file in *; do
    mv -v "$file" "$(printf 'new%02d' $i)"
    ((i++))
done


A thought: what if you have more than 100 files? How to avoid hardcoding %02d?
files=(*)
num=$(( ${#files[@]} - 1 ))
size=${#num}
for idx in "${!files[@]}"; do
    mv -v "${files[idx]}" "$(printf 'new%0*d' $size $idx)"
done


A: If you want to rename 100 files with mv, you need to call mv 100 times to rename each individual file.  There's no real way around that.
To iterate over your files in numerical order from file010 to file1000 you could use
for name in file{010..990..10} file1000
do
    # rest of code goes here
done

The {010..990..10} is a brace expansion that expands to the strings 010, 020, 030 etc. up to 990 in steps of 10.  Each such string will be prefixed by the string file.  We add file1000 at the end as its number doesn't quite fit the pattern (it's one digit too long).
To rename the files in the loop, we can keep a counter, counting from zero up.  The new filename is then constructed as the prefix file followed by the zero-filled two digit integer given by current value of the counter.
Adding this to our loop above:
count=0
for name in file{010..990..10} file1000
do
    printf -v newname 'file%.2d' "$(( count++ ))"
    mv -- "$name" "$newname"
done

Alternatively, instead of the brace expansion, we could use an arithmetic for loop like so:
for (( i = 1; i <= 100; ++i )); do
    printf -v name    'file%.3d' "$(( i * 10 ))"
    printf -v newname 'file%.2d' "$(( i - 1 ))"

    mv -- "$name" "$newname"
done


Using the Perl rename utility instead of mv:
rename -n -v 's/file(\d+)/sprintf "file%.2d", ($1\/10 - 1)/e' file*

This applies a Perl s/// (substitution) expression to each filename matching file* in the current directory.  The expression matches the number after the file substring and uses that to compute the new filename number (it's divided by 10 and decremented by one).
Remove -n to run the command "for real" (-n is a "dry run" option).
A somewhat cleaner variant that doesn't use /e to evaluate the replacement string and which only mentions file once:
rename -n -v '/(file)(\d+)/; $_ = sprintf "%s%.2d", $1, ($2/10 - 1)' file*

