3

I recently discovered the perl-based rename function but since I don't know anything about perl I can't use it properly. I found of a lot of question about the subject but nothing helped me.

I would like to rename

filename - y01m01 - extra.log
filename - y01m02 - extra.log
filename - y01m03 - extra.log
...
filename - y05m12 - extra.log

into

filename-y01m01.log
filename-y01m02.log
filename-y01m03.log
...
filename-y05m12.log

I managed to rename into

filename-y01m01 - extra.log
filename-y01m02 - extra.log
filename-y01m03 - extra.log
...
filename-y05m12 - extra.log

using rename 's/filename - y*/filename-y/ *.log but I don't know how to get rid of this - extra string at the end. The number of characters in - extra is not fixed and depends on each file so I can't just substitute the eight characters before the extension.

I guess the solution is to substitute everything after the space (and including the space) but I don't know how to code it.

Thank you for your help.

3

The perl-rename command simply uses a regular expression. Since it's Perl, it uses the very powerful Perl Compatible Regular Expresion language (PCREs). So if you want to learn how to use it, just look up PCRE.

In this case, it looks like you want to remove all spaces from the file names and also remove the string -extra. You can use two operations, just separate them with a ;:

$ rename -n 's/ //g; s/-extra//' *.log
filename - y01m01 - extra.log -> filename-y01m01.log
filename - y01m02 - extra.log -> filename-y01m02.log
filename - y01m03 - extra.log -> filename-y01m03.log
filename - y05m12 - extra.log -> filename-y05m12.log

The s/ //g means "replace all spaces with nothing" (so, remove all spaces). By default, the replacement operator that is used here (s/old/new/options) will only replace the first match. To make it replace all matches, you need the "global" option (g). That's why there's a g in s/ //g.

The s/-extra// just means "replace the first match for -extra with nothing".

If that does what you want, run it again but without the -n. That makes rename just print out what it would do without actually doing it. Very useful for testing!

If the -extra isn't a static string, but can change. You could instead remove everything after the last - and until the next .:

$ rename -n 's/ //g; s/-[^-]*\././' *.log
filename - y01m01 - extra.log -> filename-y01m01.log
filename - y01m02 - extra.log -> filename-y01m02.log
filename - y01m03 - extra.log -> filename-y01m03.log
filename - y05m12 - extra.log -> filename-y05m12.log

Here, the s/ //g will remove all spaces, as before, and the s/-[^-]*\././ means "find a - and then the longest stretch of 0 or more non-- characters following it that ends with a . and replace the whole thing with just a .. I need to escape the . (\.) on the left hand side because . means "any character" when not escaped. That isn't an issue on the right hand side.

  • Thank you for the answer and for the explanation of the syntax. – user365752 Aug 21 at 19:57
1

You can do two substitutions, one for replacing the part after the first - and then later replace all the spaces

rename -nv -- 's/-\s\w+[.]log$/.log/; s/\s+//g' *.log

Once you find the replacements are as expected, drop the -n flag.

0

Proposing this:

rename 's/(filename - y.*) - .*(\.log)/$1$2/' *.log

Your Answer

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