Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have some files named as A1.txt A2.txt ... A11.txt A12.txt, etc. I want to rename them to A0001.txt A0002.txt ... A0011.txt etc. Am I doing it right?

for file in A*.txt
do
mv ${file} ${file/-#.txt-/-"%5d".txt}
done
share|improve this question
    
Quite logical. Unfortunately, no shell I know can interpret sprintf(3) patterns like "%5d". However, if you have GNU utilities on your system (which you probably do unless you are using BSD), check out man 1 printf or info -f coreutils printf. That might do what you want. Alternately, try @John1024's idea. – thb 6 hours ago

Using Perl's rename utility:

prename 's/(\d+)\./sprintf "%04d.", $1/e' A*.txt

prename is sometimes available under the name rename. There is, however, another unrelated and incompatible utility called rename that is installed by default on some distributions.

Debian-like distributions, among others, have Perl's rename/prename installed by default. If your distribution does not, instructions for installing it can be found here

(Hat tip to Steeldriver for improved version of the command.)

Example

Consider a directory with these files:

$ ls
A12345.txt  A123.txt  A12.txt  A1.txt

Now, let's run prename:

$ prename 's/(\d+)\./sprintf "%04d.", $1/e' A*.txt
$ ls
A0001.txt  A0012.txt  A0123.txt  A12345.txt

How it works

A single substitute command is used:

s/(\d+)\./sprintf "%04d.", $1/e
  • (\d+)\. matches one or more digits followed by a period. The digits are saved in group 1.

  • The final e tells perl to evaluate the command sprintf "%04d.", $1. This command returns the digits of group 1 in format %04d meaning zero-filled four digits, followed by a period.

share|improve this answer
    
@steeldriver Your sprintf suggestion is superior. Answer updated. – John1024 5 hours ago
    
Thank you for the response. When I do "man prename", there is a manual page. But when I run "rename 's/(\d+)\./sprintf "%04d.", $1/e' A*.txt", it says "command not found". I'm not sure why. – Christin 5 hours ago
    
@Christin Curious. Try type prename and type rename. Also, what distribution/OS are you on? – John1024 5 hours ago

If you don't have the prename option suggested by @John1024, you should be able to use the printf (a built-in in bash, but also available from GUN coreutils) to format the decimal digits with the desired field width and padding - unfortunately I don't think there's a one-step shell expansion to extract the digits, the closest I can get is

for file in A*.txt
do
  base="${file%.*}"
  printf -v newfile "A%04d.txt" "${base#A}"
  mv -- "$file" "$newfile"
done
share|improve this answer
    
I believe this is the best one can get with shell: +1. (The script could be made POSIX, if anyone so desired, by replacing fourth line with newfile=$(printf "A%04d.txt" "${base#A}")) – John1024 5 hours ago
    
@John1024 thanks for clarifying the POSIX option - I wasn't sure about that – steeldriver 4 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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