I have files with following names starting with water-frames0.gro upto water-frames201.gro

water-frames0.gro  water-frames119.gro  water-frames138.gro  water-frames157.gro
water-frames116.gro  water-frames135.gro  water-frames154.gro

How do I add leading zeros and dash before numbers so that the files are sorted correctly on the terminal? I need this to work with thousands of file names, so I imagine adding a few extra zeros is useful.

I imagine the new filenames to be something as

water-frames-0000.gro  water-frames-0119.gro  water-frames-0138.gro  water- 
frames-0157.gro water-frames-0116.gro  water-frames-0135.gro  water-frames-0154.gro

I tried playing with rename and looking at previous questions, however, I couldn't find something that I could adapt.

Thank you,

2 Answers 2


Using the perl rename utility:

$ rename -n 's/(\d+)(\.gro)$/sprintf "-%04i%s", $1, $2/e' ./*.gro
rename(./water-frames0.gro, ./water-frames-0000.gro)
rename(./water-frames116.gro, ./water-frames-0116.gro)
rename(./water-frames119.gro, ./water-frames-0119.gro)
rename(./water-frames135.gro, ./water-frames-0135.gro)
rename(./water-frames138.gro, ./water-frames-0138.gro)
rename(./water-frames154.gro, ./water-frames-0154.gro)
rename(./water-frames157.gro, ./water-frames-0157.gro)

This captures the digits before .gro as $1, and the .gro itself as $2, so they can be used in the replacement, the right-hand-side (RHS) of the s/// operator. The /e modifier to the perl regular expression causes rename to evaluate the RHS as perl code. See man perlre for details. The sprintf starts with a literal - and formats $1 and $2 as a 4-digit zero-padded integer (%04i) and a string (%s).

Note 1: perl rename is also known as file-rename, perl-rename, or prename. Not to be confused with the rename utility from util-linux which has completely different and incompatible capabilities and command-line options.

Note 2: the -n option makes it a dry run, so it will only show what it would do without actually renaming any files. Remove the -n, or replace it with -v for verbose output, when you've confirmed that it does what you want.

Note 3: perl rename can take filenames as arguments from the command line or from stdin (as either newline or NUL separated filenames). rename's -0 option pairs well with input piped from find ... -print0. It also works well with find ... -exec rename ... {} +.


With zsh:

autoload -Uz zmv

To autoload that batch renaming function (best in ~/.zshrc)

zmv -n '(water-frames)(<0-999>)(.gro)' '$1-${(l[4][0])2}$3'

Remove -n when happy.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .