0

I have a couple files with the name

(a).1
(a).2
...
(a).100

Since a lot of processing tools don't really like ( and ) in the filename I thought it best to rename them to a different name. I googled for renaming files and found the wonderful tool rename where I can feed a regular expression. Okay let's try this:

$ rename -v s/\(a\)/b/ \(a\).* 

(a).1 renamed as (b).1
(a).2 renamed as (b).2
(a).3 renamed as (b).3

Hmm not what I expected. After a bit of googling I found that \( \) is a grouping operator. Which sort of makes sense since I did not escape the ( ) in the command.

I solved my renaming problem by using the . character that matches all types of values:

rename -v s/.b./b/ \(b\).*

This solution is not really nice. So how do I match ( and ) in Bash/Linux/Unix Regex?

7
  • 1
    maybe use single quotes around the round brackets? by the way, I wasn't able to reproduce any of the results you got pastebin.com/raw.php?i=yhPgtvhG the rename command you give gives an error when I run it, and does nothing when I space it out a bit. That was in cygwin though that's still bash
    – barlop
    Commented May 25, 2015 at 9:34
  • I used a Debian 8.0 with the LANG=en_US.UTF-8 environment. Maybe cygwin does some weird mangling with the input. I was able to solve this by putting the regex into quotes: rename -v 's/\(a\)/a/' \(b\).*.
    – Pascal
    Commented May 25, 2015 at 18:06
  • It could also be that the regex handling on Cygwin is different than on Linux.
    – Pascal
    Commented May 25, 2015 at 18:08
  • If I do rename -? it says rename [options] expression replacement file.. you've got the expression and the replacement but not the file. Looks after options (e.g. -v) there are 3 mandatory parameters there, separated by spaces. But your rename command only has 2 of them. i'll check my rename version (- uppercase V) $ rename -V<ENTER> rename from util-linux 2.24.2
    – barlop
    Commented May 25, 2015 at 18:57
  • I have rename [ -h|-m|-V ] [ -v ] [ -n ] [ -f ] [ -e|-E *perlexpr*]*|*perlexpr* [ *files* ]. So we have two different versions.
    – Pascal
    Commented May 25, 2015 at 19:31

1 Answer 1

1

Here's what you need:

find -name "(*)*" -type f | rename 's/\(|\)//g'

It first finds files in the current directory matching the described name, then renames them by removing the brackets. You can see the matching characters ( and ) are replaced with nothing.

3
  • Ah, I see my problem. I should have used rename 's/\(a\)/a/' instead of rename s/\(a\)/a/. What is happening here? Why did you introduce the find?
    – Pascal
    Commented May 25, 2015 at 18:00
  • I like find because you can expand the command to do many other things as well as output the list of files for verification before piping to the rename command. There's a switch that will let you test without actioning the changes, but I can't remember what it is at the moment. Commented May 25, 2015 at 21:15
  • You know that you can use find with an exec? find . -exec echo {} \;
    – Pascal
    Commented May 26, 2015 at 10:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .