Batch-renaming files

I needed to number all image files in the current directory:

# current:
16090-04.png       PySolFC_1.png
h3teampysol_20080303103813.jpg  pysol.gif
pysol_420_2.gif 175928_large.jpeg  Pysol.jpg
linux-game-pysol03.png          pysol460_big2.jpg
 
# goal:
pysolfc1.png  pysolfc2.jpeg  pysolfc3.gif
pysolfc4.jpg  pysolfc5.png  pysolfc6.jpg
pysolfc7.png  pysolfc8.gif  pysolfc9.jpg

Surprisingly easy in Common Lisp:

(loop for file in (directory "*")
     for i from 1
     do (rename-file file (format nil "pysolfc~D" i)))

In plain sh programming, I would have had to extract directory component, basename and extension, modify the basename without the extension and put them all together again. And keep track of the index manually, too.

I suppose some shell guru might come up with a neat (and probably quite unreadable) solution, but I’d rather stick to Common Lisp.

I’m curious about other solutions, esp. in Shell (ZSH allowed!), Python, Ruby and less-known languages.

Comments

  1. July 9th, 2008 | 2:42 pm

    Nice articel! Here’s one in bash, doesn’t look as neat as the lisp solution though ;-) (I hope I get the formatting right).

    i=1
    for file in $(ls *.{png,jpg,jpeg,gif}); do 
      mv $file $(printf "pysolfc%s" $i).${file/*.} 
      i=$((i+1))
    done
  2. July 9th, 2008 | 3:14 pm

    in python, it would probably look like this:

    #!/usr/bin/env python
     
    import re
    import os
     
    new_basename = 'pysolfc'
    a = 0
    for file_name in os.listdir(os.getcwd()):
            a += 1
            file_name_split = os.path.splitext(file_name)
            new_filename = (new_basename + str(a) + file_name_split[1])
            os.rename(file_name, b)
  3. July 9th, 2008 | 4:40 pm

    ZSH

    i=1 zmv '*.(*)' 'pysolfc$((i++)).$1'
  4. July 9th, 2008 | 4:54 pm

    Assuming the order of the destination files does not matter, this works in sh and the like:

    for f in * ; do
        i=$(($i+1)) ; mv $f pysolfc$i.${f#*.}
    done
  5. July 9th, 2008 | 5:19 pm

    @smoon, nice, after seeing your solution I am wondering what led me to use printf. Seems the first thing that came to my mind wasn’t the most obvious ;-).

  6. July 10th, 2008 | 1:25 am

    Yea, if you’re looking for the ultimate in renaming, you should check out zmv.

  7. July 10th, 2008 | 10:36 am

    I haven’t done anything in perl in a while, but your post got me motivated ;-). So here’s a solution in perl:

    #!/usr/bin/env perl
    use warnings;
    use strict;
     
    my $i=1;
    foreach $_ (@ARGV) {
        if( $_ =~ /(jpeg|jpg|png|gif)/ ) {
            rename($_, "pysolfc" . $i++ . ".$1");
        }
    }
  8. July 10th, 2008 | 4:56 pm

    man rename

  9. July 11th, 2008 | 11:36 pm
    #!/usr/bin/ruby
     
    require 'fileutils'
     
    Dir.glob(ARGV[0]).each_with_index do |fn, i|
      FileUtils.mv(fn, File.join(File.dirname(fn), "pysol#{i+1}" + File.extname(fn)))
    end
  10. one
    July 16th, 2008 | 2:59 pm

    i have a file, temp.txt in folder c:/TMP/Arch
    my script is in c:/script/script1.py

    i want to rename the file temp.txt with the date and time, but my script rename the file and then move the file in c:/script/

    can u tell me pls how to do ? i want the file with new name to remain in c:/TMP/Arch

    my script
    from time import time, localtime, strftime
    time_tuple = localtime(time())
    ddate = strftime(“%d.%m.%y-%H;%M;%S”, time_tuple)

    ext = “.txt”
    file = ‘c:/TMP/Arhiva/temp.txt’
    (basename,ext) = os.path.splitext(file)
    os.rename(file, ddate+ext)

  11. Fredrik
    July 17th, 2008 | 11:14 pm

    Python:

    from os import listdir, rename, path
     
    for i, name in enumerate(listdir(".")):
        rename(name, "pysolfc%d%s" % (i+1, path.splitext(name)[1]))

    or, a bit too clever perhaps:

    from os import listdir, rename, path
     
    any(rename(name, "pysolfc%d%s" % (i+1, path.splitext(name)[1]))
        for i, name in enumerate(listdir(".")))

    Python’s penalized by explicit import of subsystems (the number of “built-ins” is relatively small), and less powerful formatting. But three lines are three lines… ;-)

  12. Marco
    July 26th, 2008 | 5:15 pm

    Just a small issue with the python example, if run as a script it will rename itself.

  13. July 27th, 2008 | 9:34 am

    How cute, it’s self-modifying code.

  14. February 27th, 2010 | 6:12 pm

    cool pieces of codes

Leave a reply