There are several ways one can batch rename files in Linux. One of the possibilities is the linux command rename.
Usage
To rename files you have to supply a Perl expression. Using Perl expressions might be scary for beginners (because they look like someone hit his head on the keyboard), but they allow for complex renaming with a minimum of characters.
Although I won’t go into detail about Perl expressions here, I will try to make it a little easier for beginners to use them for batch renaming.
According to the man page of rename, this is the way to use rename:
rename [ -v ] [ -n ] [ -f ] perlexpr [ files ]
If you have not worked with Perl expressions before, this might not be enough to get you started. So let me present you with the way one would probably use rename most of the time:
rename 's/OLD/NEW/' FILES
OLD is an expressions which describes a pattern in the name filenames. If rename can find this pattern in the name of a file, it will replace this part of the filename with what is defined as NEW. The files rename should rename are defined by FILES.
Let me provide you with two examples:
Examples
Example 1 – Replacing a single word/string
Let’s start with a very simple example: Imagine, you have a lot of images that are named
picture 1.jpg picture 2.jpg ...
and you would like to replace the word “picture” with the word “image”, so that the files will be named like this:
image 1.jpg image 2.jpg ...
As describes under usage, OLD represents the part that we want to replace. As we want to replace the word “picture”, in this example OLD will be “picture”.
And because NEW defines with what OLD is replaced with, in our example. We want the OLD(=”picture”) to be replaced with “image”, so here NEW=”image”.
And because we want to do this only for all the pictures which name starts with “picture” FILES will be “picture*.jpg”.
Therefore the general command
rename 's/OLD/NEW/' FILES
becomes:
rename 's/picture/image/' picture*.jpg
It might have not been necessary for us to restrict this to the the files “picture*.jpg”. We might have just used *.jpg (all files in the current directory with the extension .jpg) or even * (all files in the current directory), because rename will only change the filename, if the pattern OLD (here: “picture”) is found in the filename. You have to be careful, though. A file with the name “just a picture.jpg” would have been renamed to “just a image.jpg”, because we told rename to replace “picture” with “image”.
Example 2
Let’s go back to Example 1. One problem I mentioned is that running
rename 's/picture/image' *.jpg
to rename files like “picture 23.jpg” to “image 23.jpg” would also rename files like “just a picture.jpg” to “just a image.jpg”, because rename would find the word “picture” and replace it with “image”, although this is not what we intended.
We could prevent this by calling rename like this:
rename 's/picture/image' picture*.jpg
This would call rename only for the .jpg files starting with the word “picture”. But this is not really a solution, because files like “picture of a sunset.jpg” would still be renamed to “image of a sunset.jpg”.
To make sure that rename really does what we want it to do, we need to be very clear about what should be renamed. Because what we want is not to replace the word “picture” with the word “image” in every case, we want to replace the word “picture” with the word “image”, but only for the files which name consists of the word “picture”, then a space and then a number and then the extension “.jpg”.
This can be achieved with the following command:
rename 's/^picture( [0-9]*\.jpg)$/image$1/' *.jpg
This might look a little scary, but is a good example of what you can do with Perl expressions. Because this would only rename the desired files. Files like “my picture 11.jpg” or “picture 28 (beach).jpg” would not be renamed and in this example that is exactly what we want to do.
Let me go through the different parts of the expression above briefly, to give you an idea of how this works. Keep in mind that this just an example and not intended as a complete tutorial. I will just try to explain to you the various elements of this expression to show you some of the possibilities and to demystify them a little bit.
When you compare the command to the general form under “Usage”, you will see that in this case:
- OLD = ^picture( [0-9]*\.jpg)$
- NEW = image$1
- FILES = *.jpg
In this example OLD makes sure that only the desired files are renamed by defining the structure of what we are looking for exactly. This works, because OLD defines what should be renamed. That means that files where the pattern/structure defined by OLD can not be found will not be renamed. Therefore, OLD automatically works as a filter to make sure that only the desired files get renamed. The trick is to make sure that OLD and NEW reflect what you wish to do. Let’s dissect it:
Let’s ignore the “^” at the beginning, the “$” at the end, the parentheses and the “\” at the moment. This leaves the following:
picture [0-9]*.jpg
This describes our basic structure. First, we have the word “picture”, then a space. [0-9] means any character from 0 to 9, which essentially means “a digit” and when putting a “*” after it, it means that there can be “any number of” digits. We need this, because we don’t know how many digits there will be. We can have files like “picture 7.jpg”, where there is only 1 digit or files like “picture 1432.jpg”, where he have four of them. So, “[0-9]*” stands for “any number of digits”, which just means: a number. And then we have “.jpg”, our extensions.
It is important to note that “[0-9]*” really means “any number of digits” and that “any number” could also mean 0. This means that the number is optional and a file named “picture .jpg” would also be renamed. In this example it probably would not make a real difference, but in general you need to be careful. If there really has to be a number and it can not be optional, you can use a “+” instead of a “*”, because “[0-9]+” means “at least one digit”. But because it will not be a problem in this case, we will keep the “*”.
Now, let’s add the parts we ignored:
The “.” is a special character which stand for “any character”. But in our pattern, we want to make clear that the filename ends with “.jpg”. But “.jpg” would be interpreted as “any character, then j, then p, then g”. Therefore a file like “picture 234Xjpg” would be renamed, because the . (which stand for “any character”) would be “X” in this case. But really want to make sure that the file ends with “.jpg” and therefore need to make it clear that the “.” really stand for “.” and not for “any character”. This can be done by escaping it with a “\”. Therefore, we need to write “\.jpg”.
The parentheses are added, because the pattern we are creating will be matching the complete filename. If we would run a command like this:
rename 's/^picture [0-9]*\ .jpg$/image/' *.jpg
A file like “picture 23.jgp” would be renamed to “image” and not to “image 23.jpg”. This is because our pattern “^picture [0-9]*\.jpg$” describes the whole filename. So the complete filename would be replace with “image”. But we just want to replace “picture” and keep the rest.
We can do this by telling rename that we want to keep everything after “picture”. While we can’t do this directly, we can put every after “picture” in parentheses and then later use this part to build our new filename, because everything within the parentheses will be saved accessible later as “$1″, so if we use the pattern
picture( [0-9]*\.jpg)
We can now see that the space, the number and the extension “.jpg” are within the parentheses and we can access this part as “$1″. When the filename is “picture 83.jpg”, $1 will therefore contain ” 83.jpg”. Then, when we define our replacement, we can tell rename to use “image$1″ as our replacement for the filename. Because $1 contains the space, the number and the extension, this would translate to “image 83.jpg”.
Now, what’s left are “^” and “$”. “^” stand for the beginning of the filename. This makes sure that files like “some picture 44.jpg” would not be renamed. This is because a pattern like “picture” means: find the word picture anywhere. Whereas “^picture” essentially means: find the word picture at the beginning of the input(=filename).
Similarly, “$” stand for the end of the input (here: filename). We use this to make sure that something like “picture 74.jpg.gz” does not get renamed.
Combining “^” and “$” therefore ensures that the filename only consists of the pattern we defined and there is nothing before “picture” and nothing after our “.jpg”.
Therefore, our final pattern is:
^picture( [0-9]*\.jpg)$
And the command to rename the files is, again:
rename 's/^picture [0-9]*\ .jpg$/image/' *.jpg
Example 4 – add a prefix to all filenames (added on 2012-05-20)
In case you want to add a prefix at the beginning of a filename, you can use this line:
rename ‘s/(.*)/PREFIX$1/’ FILES
Substitute PREFIX to whatever you want to put in front of the filename and substitute FILES for the files you want to rename (see Example 6 below for some examples)
If you run
rename ‘s/(.*)/foo_$1/’ *.txt
All the .txt files in the current directory will get an “foo_” in front of of their name. (So info.txt would be renamed to foo_info.txt, for example)
Example 5 – add a suffix to all filenames (added on 2012-05-20)
Adding a suffix at the end of a filename can be as simple as adding a prefix; you could simply run:
rename 's/(.*)/$1SUFFIX/' FILES
The problem is that this might not be what you expected, because the suffix will be added at the end of the filename, which also means after the suffix the file might already have to denote its type (e.g. “.txt”, “.tar”, “.jpg” etc. Running
rename 's/(.*)/$1boo/' info.tar
would rename the file “info.tar” to “info.tar.boo”. If that is what you want, you can use the line above, but if you would want to rename it to “infoboo.tar”, then you can use the following line:
rename 's/(.*)\.(.*)/$1SUFFIX.$2/' FILES
with this, running
rename 's/(.*)\.(.*)/$1boo.$2/' FILES
would rename “info.tar” to “infoboo.tar”.
Be aware that this will not work for files with suffixes that contain two dots (like “archive.tar.gz”).
Improvement 1 (Update 2012-05-22):
The fact that files like “archive.tar.gz” would be renamed as well and the result would certainly not be as hoped, we can try to improve the pattern above a little bit:
rename 's/^([^.]*)\.([^.]*)$/$1SUFFIX.$2/' FILES
This approach will only rename files that only contain a single dot and leave all other files alone.
Improvement 2 (Update 2012-05-22):
If you want to rename files with extensions like “.tar.gz” correctly, you can use the following approach:
rename 's/^([^.]*)\.(.*)$/$1SUFFIX.$2/' FILES
This will essentially add the suffix directly in front of the first dot. However, this approach will not work in case you have files that contain dots that are not supposed to be part of the file extension (in “some.great.file.txt”, the suffix “111″ would be added like this: “some111.great.file.txt”)
Example 6 – how to define which files to rename (added on 2012-05-20)
In the beginning I noted the general form of how to use rename:
rename 's/OLD/NEW/' FILES
I now want to give you some simple examples of what you can do with “FILES”, which tells rename which files it
should try to rename in the first place. This list is by no means complete. It just provides you with a few (hopefully useful) examples.
- to rename a single file just state its name. Example: backup.tar
- to rename several specific files just list all their names. Example: backup.tar mypicture.jpg asong.ogg
- to rename all files in the current directory just use “*” (without the “).
- to rename all files with a specific ending (e.g. .jpg) use “*ENDING”. Example: *.jpg
- to rename files with different endings, just list them all. Example: *.jpg *.jpeg *.mp3 *.txt *.ar
- to rename files that start with the same word/characters use “START*”. Example: my* old*
- to rename files that contain the same word/sequence of characters use “*WITHIN*”. Example: *good*
- you can combine all of those things. Example: my*.txt *boo*.jpg foo* test.tmp
Conclusion
I hope that this article succeeds in demonstrating how rename can be used to batch rename files (not in detail, but at least in pushing you in the right direction). And I also hope that while covering Perl expressions in detail is beyond the scope of this article, the second example gives you an idea of how powerful and useful they can be and why it can make sense to learn more about them.
Hi, how do I write a Perl expression to append a prefix to a filename?
I added two more examples (add a prefix at the beginning of a filename and add a suffix at the end of a filename).
I hope that this will help you. Please feel free to write back in case you need something different, want more information or if there is anything else I could do for you.
Thanks for the prompt reply and examples. Also, how to make rename work for more than one pattern match? Suppose I have to replace “foo” in a file name with “bar” for all files in folder. I can use the command: rename ‘s/foo/bar/’ *
But, if I have a file like foo foo.txt, it is getting renamed to bar foo.txt, not bar bar.txt. How to achieve desired result. Thanks in advance.
In this case, you can add a ‘g’ after the last slash in the pattern. This will make sure that all matches are replaced and not just the first one (which is the default behavior):
rename ‘s/foo/bar/g’ *
I need to know how to add a prefix to a batch of jpg images…
The images are titled with sku numbers or numbers and letters, which MUST remain the same, but I need to add a prefix to them, such as cf or CF denoting the manufacturer, so as not to confuse just numbers that may match with other manufacturer’s numbers.
I have only seen prefixes added and then the image sku or name gets changed to a sequential number 1 through the amount of items in the batch, such as 1,2,3,4 … with the prefix added, which is NOT helpful.
Can you assist me with this ASAP and as simple as possible, since I only know what I happen to discover… I am not computer or soft ware savvy!
THANKS!
Joyce
So, you have files like 475.jpg and 1928.jpg (for example) and you just want to add a prefix to get cf475.jpg and cf1928.jpg, for example?
This is covered as Example 4 in the article, but I noticed that the formatting in the article was off, so you probably did not notice Example 4. I corrected that. But you can make this more convenient by creating a small script (i called this add-prefix.sh):
TEST=0
if [[ $1 == '-n' ]]; then
TEST=1
fi
PREFIX=$1
shift
if [[ $TEST == 1 ]]; then
echo "just testing"
rename -n 's/(.*)/'$PREFIX'$1/' "$@"
else
rename 's/(.*)/'$PREFIX'$1/' "$@"
fi
you can then call
to add a prefix to files. To add “cf” to all jpgs in the current directory, you would call
You might want to test if what you are about to do is correct. So the best way is to backup all files, then rename them and if anything goes wrong you still have your backup. The script also allows testing. Just add “-n” as the first option and the script will not actually rename anything, but instead tell you what would be renamed. To test the above renaming, run:
And be careful, because making a mistake when batch renaming can be a real pain (hence my backup suggestion).
I hope this is what you asked for. Please feel free to get back to me in case you need further help or I somehow misunderstood what you wanted to do.
Hello,
I have two files where the date varies. I would like renamed with the REN command only the latest. How can i do this if you can help me?
Z__C_EDZW_20130412000000_fax01,waf_swc_eur_000024_700150__EGRR.png
Z__C_EDZW_20130413000000_fax01,waf_swc_eur_000024_700150__EGRR.png
This file is last: Z__C_EDZW_20130413000000*
Best regards,
Petar
Hi,
The “ren” command? Are you on windows? In this case I can not help you, because I don’t have windows myself and am not familiar with its command line.
In your case I would not use just rename (maybe I would not even use rename at all). If the files always have this format and are in a separate directory I would write a script and have it go into this directory and then do f=$(ls|tail -1) and this would set f to the name of the file with the latest date. And then I would rename it.
But if the files are not in a separate directory or if the format changes, this would not necessarily work. And then it also depends on how the files should be renamed. If it should just be renamed as something fixed (like “latest” or “foobar”), I would not use rename, but mv instead.
If you are not on windows and provide me with some further information I might help you with a small script. If you are on windows, I might not be able to solve the problem, but I might be able to help you a little.
Hi,
The “ren” command? Are you on windows? In this case I can not help you, because I don’t have windows myself and am not familiar with its command line.
In your case I would not use just rename (maybe I would not even use rename at all). If the files always have this format and are in a separate directory I would write a script and have it go into this directory and then do f=$(ls|tail -1) and this would set f to the name of the file with the latest date. And then I would rename it.
But if the files are not in a separate directory or if the format changes, this would not necessarily work. And then it also depends on how the files should be renamed. If it should just be renamed as something fixed (like “latest” or “foobar”), I would not use rename, but mv instead.
If you are not on windows and provide me with some further information I might help you with a small script. If you are on windows, I might not be able to solve the problem, but I might be able to help you a little.
I have 100′s of “.jpg” files with different names. I want to give all of them the same name followed by a number such as (image1.jpg, image2.jpg and so on). How can do this in linux.
You can create a small script like this:
basename="image"
if [ $# -ne 1 ]; then
echo "usage: this script needs exactly 1 parameter"
exit 1
fi
if [ ! -d "$1" ]; then
echo "$1 is not a directory"
exit 1
fi
cd "$1"
i=1
for img in *.jpg; do
mv -n "$img" $(printf "$basename%d.jpg" $i)
let i=i+1
done
Then you just call the script (let’s imagine it is called script.sh) with the directory in which the images are; like this:
But this script will be “problematic”, if you use it several times with the same directory, because then there are already files named “image1.jpg” etc. As it is the script will not overwrite existing files (because of the -n switch for mv), so data loss should not be a problem, but this could happen:
If you have the file “a.jpg and image1.jpg”, then it might try to rename a.jpg to image1.jpg. This won’t be done, because image1.jpg already exists. Then it tries to rename image1.jpg to image2.jpg and you now have the files a.jpg and image2.jpg.
There are numerous ways to improve it, but it would depend on the situation and also on the desired workflow. You might find it working for you as it is. If not, just write back and I try to improve it.
EDIT: Just a tip: always make a backup before running new scripts like this! I tested it with a few empty files, but everytime I use a new script with real data, I make a backup before, because you can’t back otherwise.
many thanks for this detailed and useful information on ‘rename’ CMD!!
much appreciated documentation!
tell me to rename folder end with asd to space