Renaming multiple files with rename

I need to rename files in batch–the other questions I browsed don’t exactly address my problem. The names of my files are generated non-deterministically, so I can’t predict what they will be named. I do know that they will start with NORMAL and end with -lib*. I’d like to replace everything in between with some string X. For example,

|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib1.concordant
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib1.deletion
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib1.divergent
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib1.inversion
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib1.translocation
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib4.concordant
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib4.deletion
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib4.divergent
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib4.insertion
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib4.inversion
|   |   |-- NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib4.translocation

So it will probably be of the form rename "s/something/X/", but I don’t know what that something should be, as I don’t know how to use regex.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

The useful Perl powered rename isn’t always available on all distros. For example, Fedora and CentOS (and presumably RedHat) use a basic rename utility that does basic search and replace and nothing much else.

If you’re unfortunate enough to be using one of those, then something like the following may help:

for oldname in *; do
    newname=$(echo "$oldname" | sed -e 's/(NORMAL).*(-lib.*)/1X2/')
    mv "$oldname" "$newname"
done

Method 2

If you are lucky enough to have rename available, then the following should be sufficient:

rename 's/(NORMAL).*(-lib)/$1X$2/' *

Method 3

There are two unrelated programs called rename. The one found on Debian and derivatives (Ubuntu, Mint, …) is a Perl script, and its first argument is a Perl expression that transforms the old name into the new name. With that script, you can do

rename 's/.*-lib/NORMAL_X-lib/' NORMAL_*-lib*

The s operator performs a regular expression replacement. There are oodles of regular expression tutorials on the web, e.g. 1. .*-lib matches the string up to the last occurrence of -lib (.* matches any string), so s/.*-lib/NORMAL_X-lib/ replaces the NORMAL_blahblah-lib part by NORMAL_X-lib.

If you have a Linux distribution that isn’t derived from Debian, then the rename utility is one that is suitable for almost no practical task. You can use a shell loop instead.

for x in NORMAL_*-lib*; do
  mv "$x" "NORMAL_X-lib${x##*-lib}"
done

${x##*-lib} is the value of the variable x minus the part up to the last occurrence of -lib. This is standard parameter expansion syntax.

This task is easiest in zsh, with its zmv function. Put autoload -U zmv in your .zshrc (or run it on the command line for a once-off), then run

zmv 'NORMAL_*-(lib*)' 'NORMAL_X-$1'

Method 4

You could consider using lookarounds, like (?<=NORMAL).*?(?=-lib) i.e.

$ rename -v -n -- 's/(?<=NORMAL).*?(?=-lib)/X/' *
NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib4.insertion renamed as NORMALX-lib4.insertion
NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib4.inversion renamed as NORMALX-lib4.inversion
NORMAL_H_LS-A7-A0CE-10A-01D-A017-09-lib4.translation renamed as NORMALX-lib4.translation


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x