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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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