JL Peyret
JL Peyret

Reputation: 12154

bash: using rename to left pad filenames with a zero under when their prefix is too short

I'm using a naming convention with number prefixes to track some files. But I am running out with 2-digit prefix. So, instead of 11.abc 12.def I want to move to 011.abc 012.def. I already have some 013.xxx 014.yyy.

Trying this in an empty directory:

touch 11.abc 12.def 013.xxx 014.yyy

ls -1 gives:

013.xxx
014.yyy
11.abc
12.def

Try #1:

This should match anything that starts with 2 digits, but not 3.

rename -n 's/^\d\d[^\d]/0$1/' *

Now I was kind of hoping that $1 would hold the match, like 11, with 0$1 giving me 011.

No such luck:

Use of uninitialized value $1 in concatenation (.) or string at (eval 2) line 1.
'11.abc' would be renamed to '0abc'
Use of uninitialized value $1 in concatenation (.) or string at (eval 2) line 1.
'12.def' would be renamed to '0def'

On the positive side, it's willing to leave 013 and 014 alone.

Try #2 rename -n 's/^\d\d[^\d]/0/' *

'11.abc' would be renamed to '0abc'
'12.def' would be renamed to '0def'

Since this is regex based, can I somehow save the match group 11 and 12?

If I can't use rename I'll probably write a quick Python script. Don't want to loop with mv on it.

And, actually, my naming covention is 2-3 digits followed by a dot, so this is a good match too.

rename -n 's/^\d\d\./<whatever needs to go here>/' *

For what it's worth, I am using the Homebrew version of rename, as I am on a mac.

Upvotes: 1

Views: 202

Answers (2)

pjh
pjh

Reputation: 8064

rename is problematic because it's not part of POSIX (so it isn't normally available on many Unix-like systems), and there are two very different forms of it in widespread use. See Why is the rename utility on Debian/Ubuntu different than the one on other distributions, like CentOS? for more information.

This Bash code does the renaming with mv (which is part of POSIX):

#! /bin/bash -p

shopt -s nullglob  # Patterns that match nothing expand to nothing.

for f in [0-9][0-9].* ; do
    mv "$f" "0$f"
done
  • shopt -s nullglob is to prevent problems if the code is run in a directory that has no files that need to be renamed. If nullglob isn't enabled the code would try to rename a file called '[0-9][0-9].*', which would have unwanted consequences whether or not such a file existed.

Upvotes: 1

UtLox
UtLox

Reputation: 4154

try this:

rename 's/^(\d{2}\..*)/0$1/' *

Upvotes: 1

Related Questions