What's the difference between 'rename' and 'mv'?

It's basically what it says on the lid, for both.

mv is a standard utility to move one or more files to a given target. It can be used to rename a file, if there's only one file to move. If there are several, mv only works if the target is directory, and moves the files there.

So mv foo bar will either move the file foo to the directory bar (if it exists), or rename foo to bar (if bar doesn't exist or isn't a directory). mv foo1 foo2 bar will just move both files to directory bar, or complain if bar isn't a directory.

mv will call the rename() C library function to move the files, and if that doesn't work (they're being moved to another filesystem), it will copy the files and remove the originals.

If all you have is mv and you want to rename multiple files, you'll have to use a shell loop. There are a number of questions on that here on the site, see e.g. this, this, and others.


On the other hand, the various rename utilities rename files, individually.

The rename from util-linux which you mention makes a simple string substitution, e.g. rename foo bar * would change foobar to barbar, and asdffoo to asdfbar. It does not, however, take a regular expression!

The Perl rename utility (or various instances of it) takes a Perl expression to transform the filenames. One will most likely use an s/pattern/replacement/ command, where the pattern is a regular expression.

Both the util-linux rename and the Perl rename can be used to move files to another directory at the same time, by making appropriate changes to the file name, but it's a bit awkward. Neither does more than call rename() on the files, so moving from one filesystem to another does not work.

As for which rename you have, it may depend on your distribution, and/or what you have installed. Most of them support rename --version, so use that to identify which one you have.


mv

It's a basic command line designed to do one thing and do it well (Unix philosophy) : move file(s) or directorie(s).

You can hack STDOUT & STDIN¹ to modify on the fly the destination string, but it's just not a smart hack

rename (Perl's one)

warning There are other tools with the same name which may or may not be able to do this, so be careful.

When people talk about rename, we think about this one, not the ELF one, less powerful (magic?).

It's not basic, it's Perl. You can pass some Perl's functions inside, and it's extremely powerful.

Consider this example :

You want to rename a bunch of files like

foobar_1.txt
foobar_2.txt
foobar_3.txt

You can prepend zeros to the digits with sprintf() like this (using regex, heh, it's Perl :D ) :

rename 's/(\d+)/sprintf("%04d", $1)/e' foobar_*.txt

Now you have :

foobar_0001.txt
foobar_0002.txt
foobar_0003.txt

Not really a basic command, isn't it ?

rename is not really designed to move dir(s), but it can do it :

$ mkdir -p /tmp/foo/bar/base
$ touch /tmp/foo/bar/base/file
$ rename 's!/tmp/foo/bar/base/file!/tmp/file!' /tmp/foo/bar/base/file

The moved file

/tmp/file

¹ some code we see on *.stackexchange.* websites

enter image description here

for FILE in `ls *.txt`
do
    mv ${FILE} `echo ${FILE} | sed 's/anything_ugly/anything_still_ugly/'`
done

It's not the way to go, it's plain buggy, just to explain why to use the right tool at the right moment


mv simply changes the name of the file (it can also move it to another filesystem or path). You give it an old name and a new name, and it changes the file to the new name or location. rename is used to make bulk naming changes. Say you had a thousand files, foo000.log through foo999.log and you wanted to change them to bar000.log through bar999.log. With mv you'd have to do mv foo000.log bar000.log, mv foo001 bar001.log, etc. or else write a script. With rename you simply do rename foo bar foo*.log, and voila, a thousand files are changed in an instant! Pretty cool. Check out the man rename page again for details.

Tags:

Rename

Mv