Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This question already has an answer here:

I'm an absolute newbie in the unix area so forgive me off the bat if I've gone about this the wrong way.

I have a series of files I need to rename which all have the pattern " (*)" in them. Eg;

001 (1).txt
002 (1).txt
003 (2).txt

My desired output is to rename the files to 001.txt, 002.txt, 003.txt. Note the real files vary in length and extension type (this is my test batch).

I have searched the net and SE and come up with the following which gives me the desired output in the terminal.

ls *\(*\)* | sed 's/\(.*\)\( (.*)\)\(.*\)/mv & \1\3/'

mv 001 (1).txt 001.txt
mv 002 (1).txt 002.txt
mv 003 (2).txt 003.txt

However once I pipe it to sh I get the error below.

sh: line 1: syntax error near unexpected token `('
sh: line 1: `mv 001 (1).txt 001.txt'

I know it has to do with the \( (.*)\) section. I've tried escaping the internal parentheses but then that doesn't give me the desired output. I've also searched for regex ways to say search for the whitespace followed by any 3 characters but have had no luck.

I know there are easier ways to achieve what I want but I went with sed as thus far it was the only thing I could vaguely understand. Very much appreciate any input into getting the above line working and then considering easier approaches.

share|improve this question

marked as duplicate by slm, Anthon, Thomas Nyman, strugee, jasonwryan Jan 21 at 7:09

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

3 Answers 3

up vote 1 down vote accepted

There is a rename command that does just this, but I've never used it.

Your script is close. Try this:

ls -d -- *\(*\)* | sed 's/\(.*\) (.*)\(.*\)/mv -- "&" "\1\2"/'

Note that '(' is a special character to the shell. Putting it in double-quotes cancels its special meaning.

share|improve this answer
    
Thanks for your reply. It worked. –  HAKS Jan 21 at 21:17
for i in *'('*')'*
do
    mv "$i" `echo $i | sed 's/\(.*\) (.*).\(.*\)/\1.\2/'`
done
share|improve this answer
    
Thanks for your reply. Worked fine. Good to see alternative options. –  HAKS Jan 21 at 21:27

Using Bash

You can use this command to do it using strictly just Bash:

$ for file in ./*; do mv "$file" "${file/ (*)/}"; done

Example

$ ls -1
001 (1).txt
002 (1).txt
003 (2).txt

Running the above command:

$ for file in ./*; do mv "$file" "${file/ (*)/}"; done
$ ls -1
001.txt
002.txt
003.txt

Using rename

Some distros (Debian/Ubuntu) include the command rename. You can do what you want like so using this version of rename.

$ rename -v 's/ \(.*\)\./\./' ./*.txt

Example

$ rename -v 's/ \(.*\)\./\./' ./*.txt
001 (1).txt renamed as 001.txt
002 (1).txt renamed as 002.txt
003 (2).txt renamed as 003.txt

$ ls -1
001.txt
002.txt
003.txt

However, Red Hat distros do not include this version of rename.

References

share|improve this answer
    
Thanks for providing alternate options. The first one worked as expected however the rename one wouldn't. I'll do a little research into it and see if i can work it out. –  HAKS Jan 21 at 21:26
    
What's the distro? –  slm Jan 21 at 21:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.