20

It's not completely clear to me, but what is the difference between mv and rename (from util-linux-ng 2.17.2 as /usr/bin/rename)? Are there advantages of one over the other beyond rename accepting regular expressions and mv doesn't? I believe rename can also handle multiple file renames at once, whereas mv does not do this.

I couldn't find a clear indication in their man pages what else sets them apart or through some investigation on my own.

Kusalananda
  • 333,661
Urda
  • 326
  • 2
    Let's make sure we're talking about the same things; what are the outputs from type -a rename and rename --version ? – Jeff Schaller Apr 04 '19 at 17:57
  • 1
    @JeffSchaller It's more of a curiosity on my part, but on one of my *nix machines I get rename is /usr/bin/rename and rename (util-linux-ng 2.17.2) respectively. – Urda Apr 04 '19 at 17:58
  • 7
    There are a few different renames out there, and it could have been an alias/function/script, so I just wanted to make sure we knew what it was. Thank you! Please feel free to edit those outputs into your question. – Jeff Schaller Apr 04 '19 at 18:03
  • @JeffSchaller no worries, actually this link was one I just found that showed me rename can mean different things in different distros. – Urda Apr 04 '19 at 18:05
  • 5
    It seems like your question contains its answer.   “What’s the difference between a jet and a tricycle, other than the fact that a jet can *fly*, and can go several thousand times faster?”    :-)    ⁠ – G-Man Says 'Reinstate Monica' Apr 04 '19 at 18:10
  • @G-Man hah I thought that as well, but I was seriously stumped and didn't find any other thread or topic on the matter helpful to me. But I also didn't know about the different rename situation as linked in my earlier comment! – Urda Apr 04 '19 at 18:11

4 Answers4

24

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.

ilkkachu
  • 138,973
  • Not only 'regular expression' but function if need it – Gilles Quénot Apr 04 '19 at 22:38
  • @GillesQuenot, well, yeah, you could do e.g. rename '$_=lc' * to lowercase filenames. But I think the most common case is to use s/// (which I mentioned) and the pattern part of it is a regex; I don't think you can use a function there. You could do it in the replacement part, though. – ilkkachu Apr 05 '19 at 08:35
  • @MyWrathAcademia, That first example in the man page works for me (it just does things differently from the other one). Also, the reason I linked to Debian's manpages is that at least there it's made very clear that the man page for rename.ul is and will be for the util-linux version, and not for any of the others. – ilkkachu Apr 23 '19 at 23:02
  • @ilkkachu , do you mind adding an explanation to that first example either in your answer or in a comment. It's different from the example in man rename so it would be good to know your understanding of the debian example – bit Apr 24 '19 at 20:34
  • @MyWrathAcademia, I assumed you mean the rename foo foo0 foo?; rename foo foo0 foo?? example, since that was the only difference between those two man pages I saw. That pair of commands works because the first one adds a zero to the names of each single-digit filename, and after that, the second adds (another) zero each two-digit filename. That second set includes the files renamed by the first command. Using rename foo foo00 foo? as the first command also works, it just adds two zeros at one go. – ilkkachu Apr 24 '19 at 20:49
2

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)

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 ?

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

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

Stephen Kitt
  • 434,908
  • +1 for sprintfing with rename – Archemar Apr 04 '19 at 19:30
  • Why do you say stackexchage.* ?  Is there any stackexchage.* other than stackexchage.com ?  To partially answer my own question, (1)  stackoverflow.es is a Spanish-language site that appears to be legitimate, but has no relationship to Stack Overflow.  (2)  stackexchange.es is a “Buy this domain” site that uses a certificate registered to parkingcrew.net, which appears to be a brazen operation to monetize parked domain names.  (3)  stackoverflow.ru uses a certificate registered to stackoverflow.com and attempts to redirect to ru.stackoverflow.com, but doesn’t do it correctly. – G-Man Says 'Reinstate Monica' Jan 30 '23 at 21:30
  • StackExchange globally: superuser.com unix... Ubuntu... – Gilles Quénot Jan 31 '23 at 07:04
2

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.

dhag
  • 15,736
  • 4
  • 55
  • 65
0

mv moves or renames files and directories and will back them up; rename just renames files.

mv has more capabilities and options. Look at the switches in the man pages for each to see the differences in capabilities. Let's take a look using man in Ubuntu 18.04LTS (your mileage may vary depending on the version of each package):

mv options (omitting help and version)

   --backup[=CONTROL]  
          make a backup of each existing destination file  

   -b     like --backup but does not accept an argument  

   -f, --force  
          do not prompt before overwriting  

   -i, --interactive  
          prompt before overwrite  

   -n, --no-clobber  
          do not overwrite an existing file  

  If you specify more than one of -i, -f, -n, only the final one takes effect.  

   --strip-trailing-slashes  
          remove any trailing slashes from each SOURCE argument  

   -S, --suffix=SUFFIX  
          override the usual backup suffix  

   -t, --target-directory=DIRECTORY  
          move all SOURCE arguments into DIRECTORY  

   -T, --no-target-directory  
          treat DEST as a normal file  

   -u, --update  
          move only when the SOURCE file is newer than the destination file or when the destination file is missing  

   -v, --verbose  
          explain what is being done  

   -Z, --context  
          set SELinux security context of destination file to default type  

rename options (omitting help and version)

   -s, --symlink   
          Do not rename a symlink but its target.  

   -v, --verbose  
          Show which files where renamed, if any.  

   -n, --no-act  
          Do not make any changes.  

   -o, --no-overwrite  
          Do not overwrite existing files.            
K7AAY
  • 3,816
  • 4
  • 23
  • 39