5

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.

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
HAKS
  • 53

3 Answers3

8

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

slm
  • 369,824
1

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.

ash
  • 7,260
1
for i in *'('*')'*
do
    mv "$i" `echo $i | sed 's/\(.*\) (.*).\(.*\)/\1.\2/'`
done
unxnut
  • 6,008