Using rename to change prefix of files recursively in Ubuntu, (regex not working)

Viewed 123

I am using rename available in ubuntu:

$ rename --version
/usr/bin/rename using File::Rename version 0.20

This is what my directory looks like:

$ tree .
.
├── awp-3
├── bar
│   └── wp-2
└── wp-foo
    └── wp-1

My goal is that I want to rename all files and folders with the prefix wp- to static-

This is what I ran:

$ shopt -s globstar

$ rename -n 's/wp-/static-/' **
rename(awp-3, astatic-3)
rename(bar/wp-2, bar/static-2)
rename(wp-foo, static-foo)
rename(wp-foo/wp-1, static-foo/wp-1)

This is almost what I want. The file awp-3 should not have been renamed.

So I did this instead:

$ rename -n 's/^wp-/static-/' **
rename(wp-foo, static-foo)
rename(wp-foo/wp-1, static-foo/wp-1)

For some reason, this didn't change the filename of wp-1 or wp-2.

How can i use rename to change wp-2, wp-foo and wp-1 to static-*?

2 Answers

The ^ anchor only matches beginning of line. I'm guessing you want

rename -n 's%(^|/)wp-%$1static-%' **

Another way to tighten this up is to say wp must only occur adjacent to a word boundary.

rename -n 's/\bwp-/static-/' **

Renaming files recursively using rename is problematic: you have to make sure that you rename the inner files/subdirectories first before renaming the parent directories. Simply adding the /g modifier to rename all the levels (e.g. s!(^|/)wp-!$1static-!g to rename(wp-foo/wp-1, static-foo/static-1) won't work.

It's better to use a tool that supports recursive operation, such as perlmv. I suggest a perl-based tool because rename is also a perl-based tool and they work similarly. Unfortunately there's not yet a Debian/Ubuntu package for perlmv, so you'll need to install it via a CPAN client (e.g. cpanm -n App::perlmv). Once you have perlmv:

% perlmv -R -de 's/^wp-/static-/' *

The result:

% tree .
.
├── awp-3
├── bar
│   └── static-2
└── static-foo
    └── static-1

Notes:

  • you don't have to use ** with perlmv, just *.

  • -R is for recursive.

  • dry-run mode in perlmv is -d not -n. Once you see that perlmv will do what you want, you can omit the -d or replace it with -v (verbose).

  • you need to add -e before specifying perl code.

Related