I have many files in a directory having extension.


I want to remove the numbers from extension and output should be like


Can anyone please help me with the shell script for that?i am using CentOs 6.3.

  • recursively or flat? – Jacob Vlijm Jun 10 '15 at 7:34
  • recursively would be better :) – vishal Jun 10 '15 at 7:37
  • You do realize that these are COPIES of the file ending with .text? (ie. you downloaded the same file 3 times in this case). – Rinzwind Jun 10 '15 at 9:37
  • Which file should be kept? If you have foo.txt(1), foo.txt(2), which one should overwrite the other? – terdon Jun 10 '15 at 9:57
  • i dont want to overwrite them because i dont have multiple files with same name , i have all the files having different names...i just want to rename foo.txt(1) to foo.txt and foog.txt(2) to foog.txt(just example) – vishal Jun 10 '15 at 10:29

Start the one-liner in the folder where the files are saved or change the path for the find command. In the following examples find . the path is . (dot).

Test with:

find . -type f -print0 | xargs -I{} -0 rename -v -n  's/\([0-9]+\)$//' {}

Rename with:

find . -type f -print0 | xargs -I{} -0 rename -v  's/\([0-9]+\)$//' {}

The command finds all files recursively and removes all occurrences of (<any_number>) at the end of the file name.

Remove the $ in 's/\([0-9]+\)$//' to remove all occurrences somewhere in the file name, eg:

find . -type f -print0 | xargs -I{} -0 rename -v  's/\([0-9]+\)//' {}


% ls -oga
-rw-rw-r--  1 0 Jun 10 09:34 .foo(1)
-rw-rw-r--  1  0 Jun 10 09:34 .bar(2)
% find . -type f -print0 | xargs -I{} -0 rename -v  's/\([0-9]+\)$//' {}
% ls -aog
-rw-rw-r--  1    0 Jun 10 09:34 .foo
-rw-rw-r--  1    0 Jun 10 09:34 .bar
  • 2
    Maybe use s/\([0-9]+\)$// to only remove the brackets at the end of the filename. Anyway +1 good solution – chaos Jun 10 '15 at 7:42
  • it is not working for my directory: -rw-rw-r-- 1 DSC02687.JPG(1) -rw-rw-r-- 1 DSC02688.JPG(1) [msearch@kaldi vishal]$ find . -type f -print0 | xargs -I{} -0 rename -v 's/([0-9]+)$//' {} [msearch@kaldi vishal]$ ll total 8940 -rw-rw-r-- 1 DSC02687.JPG(2) -rw-rw-r-- 1 DSC02688.JPG(1) – vishal Jun 10 '15 at 8:00
  • This is the rename command: rename -v 's/\([0-9]+\)$//' {} don't forget the backslashes. – A.B. Jun 10 '15 at 8:06
  • i have run the same command which you have given but it is not changing the extension. – vishal Jun 10 '15 at 8:14
  • 2
    +1, anyway just find . -type f -print0 | xargs -0 rename -v 's/\([0-9]+\)$//' will do – kos Jun 10 '15 at 8:23
for i in *.text*; do mv "$i" "$(echo "$i" | sed 's/([0-9]\{1,\})$//')"; done 

just need to change the extension (.text or any other extension) according to need.

  • This will not do recursively..furthermore this is very inefficient way as rename can do it very simply.. – heemayl Jun 10 '15 at 12:07

Using python:

#!/usr/bin/env python2
import os, re
for root, dirs, files in os.walk('/path/to/directory'):
    for f in files:
        oldname = os.path.join(root, f)
        newname = os.path.join(root, re.search(r'(?<=/)[^/]+(?=\(\d+\)$)', oldname).group())
        os.rename(oldname, newname)

Considering the first part of file names are different (as you have mentioned it already), so no chance of overwriting.

  • os.walk will traverse all subdirectories under the mentioned directory

  • oldname will contain the name of the file to be changed. os.path.join will add the filename with the directory path by os.path.join

  • newname will contain the name what oldname will be change to. Here we have used the re module to get the file name and then added the filename to the path to directory by os.path.join

  • os.rename will simply rename the files accordingly.

Before :

├── 1 spam.text(1)
├── 1.text(23)
└── bar
    ├── 1 egg.text(10)
    └── 3test.text(5)

After :

├── 1 spam.text
├── 1.text
└── bar
    ├── 1 egg.text
    └── 3test.text

This is "additional comment" and not a complete answer by itself.

This is a really long way of 'explaining' a minor concept - it will appear long and pedantic except if the reader has missed the point.

Short summary:

If there are more than one file of name like foo.txt[(n)]

  • foo.txt, foo.txt(1) -- rename -- > no change
    Appears that nothing happened. It did.

  • foo.txt(1), foo.txt(2) -- rename --> foo.txt, foo.txt(2) (probably)
    One file renamed, one not.


You say that you do not have duplicate files.
You may be correct
BUT - the following is trivially obvious if you know it but a subtle trap if you have not met it before.

As far as the system is concerned

foo.txt = = foo.txt(1) = = foo.txt(2) = etc

regardless of file content or size.

ie If you have two files names foo.txt with or without (n) after them then the system thinks they are duplicates and/or they are duplicates.
Either way, a rename process will fail.

If the rename process would create two files with the same name then it will fail when the attempt is made to create the 1st-duplicate. But

In one case the failure will not create any output so it will appear that "nothing happened" when really "copying failed due to name collision" happened. This case occurs when one file has no (n) suffix and one other has.
eg if existing files are foo.txt and foo.txt(1) then the rename of foo.txt(1) would create a duplicate if allowed so will not occur, and so no action will take place.
foo.txt, foo.txt(1) -> no change

But if existing files are eg foo.txt(1) and foo.txt(2) then the rename of foo.txt(1) would NOT create a duplicate so will occur BUT the rename of foo.txt(2) subsequently would create a duplicate if allowed so no second-file-rename action will take place.
foo.txt(1), foo.txt(2) -> foo.txt, foo.txt(2) (probably)

  • Thanks @russel for explanation: but i have already got a simpler and much easier command for the same which i posted in the answer section. – vishal Jun 10 '15 at 11:41
  • @Vishal Mine is not an explanation of how to do it, but an explanation of what can go wrong so it seems not to work. In Windows "DOS" command shell it's worse as the short form of file names can have semi arbitrary characters assigned by 'Microsoft' which can clash with real file names during some renaming operations. FWIW :-) – Russell McMahon Jun 10 '15 at 11:51
  • yes i am aware of that. that's why i already had moved all the original files to different directory. i was searching the solution for only those file which has numbers in extensions :) – vishal Jun 10 '15 at 11:53
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – s3lph Jun 10 '15 at 14:46
  • @the_Seppi - (1) Indeed. That's why the first sentence reads - "This is "additional comment" and not a complete answer by itself." (2) You can only fit so much in a pint pot. I was not requesting clarification, nor yet critiquing. The object was to point out an obvious yet inobvious trap that, from his several exchanges with others, it appeared he was falling in to. From his responses to me it seems he may be inside the event horizon as he has moved out original files and is now renaming duplicates to have the same name as the originals. IF they are not in fact exact duplicates... – Russell McMahon Jun 10 '15 at 15:14

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