6

I have a lot of files I'm trying to rename, I tried to make a regular expression to match them, but even that I got stuck on the files are named like:

File Name 01

File Name 100

File Name 02

File Name 03

etc, I would like to add a "0" (zero), behind any of file that are less than 100, like this:

File Name 001

File Name 100

File Name 002

File Name 003

The closest I got to so much as matching them was using this find -type d | sort -r | grep ' [1-9][0-9]$' however I could not figure out how to replace them. Thanks in advance for any help you can offer me. Im on CentOS if that is of any help, all this is being done via SSH.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
linux_rookie
  • 85
  • 2
  • 6
  • Do your filenames actually contain spaces? – Mark Byers Dec 02 '09 at 23:16
  • Yes, they do they look like: "File Name 01" "File Name 101" – linux_rookie Dec 02 '09 at 23:17
  • 1
    Can you elaborate on the "tools" available on the machine? Do you have perl, python, ruby or similar installed? – R. Martinho Fernandes Dec 02 '09 at 23:19
  • 2
    could you clarify which are the names of the files you're trying to match are, and which are the names you're trying to avoid matching? I'm a little confused here. – mpobrien Dec 02 '09 at 23:20
  • Perl (5.8.8) is on the machine, however python and ruby are not, I am familiar enough to go through yum and install them if necessary. – linux_rookie Dec 02 '09 at 23:21
  • mpobrien; im trying to match files named like: "Folder Name 12" "Folder Name 120" There is 2 words in the names the names are all the same, its just the numbers are different, in short I want to add a zero before any number under than 100, so Im trying to turn "File Name 10" into "File name 010", let me know if thats a bit more clear. Sorry for any confusion – linux_rookie Dec 02 '09 at 23:25
  • Are you running a program locally that must rename files on a remote system via SSH? Or can you install and run a program on the target system? – daotoad Dec 02 '09 at 23:26
  • daotoad, its being done remotely via SSH. I can install stuff on the target system. – linux_rookie Dec 02 '09 at 23:31

9 Answers9

13
perl -e 'foreach $f (glob("File\\ Name*")) { $nf = $f; $nf =~ s/(\d+)$/sprintf("%03d",$1)/e; print `mv \"$f\" \"$nf\"`;}'

A bit overkill maybe, but it does what is asked.

Jeff B
  • 29,943
  • 7
  • 61
  • 90
10
find . -type d -print0 | xargs -0 rename 's/(\d+)/sprintf "%03d", $1/e' 

or something like that, provided

  1. You have GNU find and GNU xargs (for -print0 and -0)
  2. You have the 'rename' utility that comes with perl
  3. There's only one group of digits in the filename. If there's more than one, then you need to do something with the regex to make it only match the number you want to reformat.
hobbs
  • 223,387
  • 19
  • 210
  • 288
4

Is this a one-time thing? If so, I'm going to suggest something that might seem to be a cop out by many programmers here:

Pipe the output of your command (find -type d | sort -r | grep ' [1-9][0-9]$') to a file and use an editor along with some global search/replace magic to create a script that does the renames.

Then throw away the script.

There's little fuss and little chance that you'll end up shooting yourself in the foot by having some attempt at a clever (but inadequately debugged) one-liner go off into the weeds on your files.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
2

Run two commands, in this order:

$ rename 's/File Name (\d)$/File Name 0$1/' *
$ rename 's/File Name (\d\d)$/File Name 0$1/' *

First one renames everything less than 10 and prepends a zero. The second one renames everything less than 100 and prepends a zero. The result should be three digits for all filenames.

ire_and_curses
  • 68,372
  • 23
  • 116
  • 141
1

In my debian it works well with rename, tested with 300 files.

 perl -e 'map `touch door$_.txt`, 1..300;'
 rename 's/(\d+)\.txt/sprintf("%03d.txt", $1)/e' *.txt
pavel
  • 377
  • 2
  • 11
0

I think mmv is your friend here.

Ken
  • 1,066
  • 1
  • 10
  • 17
0

you could do something using perl or ruby.

put all this files in the same directory

dirlisting = DIR.entries('.')

dirListing.each do |file| 
 num = file.match(/\d+$/).to_i
 if num < 100
   find the position where start the number, with index and inject the 0 there.
 end
end
VP.
  • 5,122
  • 6
  • 46
  • 71
0
use strict;
use File::Copy;

my @files = glob 'File*Name*';

foreach my $filename (@files) {
    if ($filename =~ m`^.*File.*Name.*?(\d+)`) {
        my $number = $1;
        next if ($number > 99);
        rename $filename, sprintf("FileName%03d",$number);
    }
}
chris d
  • 19
  • 3
0

if your remote has bash shell

for i in File*; 
do 
    case "${i##* }" in  [0-9][0-9] ) 
      echo  mv "$i" "${i% *} $(printf "%03d" ${i##* })" ;; 
    esac; 
done

remove "echo" to do actual renaming

ghostdog74
  • 327,991
  • 56
  • 259
  • 343