Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: Recursively rename all files and directories

Tags:

linux

perl

I need to recursively rename every file and directory. I convert spaces to underscores and make all file/directory names to lowercase. How can I make the following script rename all files in one run? Currently the script needs to be run several times before all the files/directories are converted. The code is below:

#!/usr/bin/perl

use File::Find;

$input_file_dir = $ARGV[0];

sub process_file {
        $clean_name=lc($_);
        $clean_name=~s/\s/_/g;
        rename($_,$clean_name);
        print "file/dir name: $clean_name\n";
}
find(\&process_file, $input_file_dir);
like image 577
user305801 Avatar asked Mar 31 '10 23:03

user305801


2 Answers

You either need to specify bydepth => 1 in the options you pass to find or call finddepth. From perldoc File::Find:

bydepth

Reports the name of a directory only AFTER all its entries have been reported. Entry point finddepth() is a shortcut for specifying { bydepth => 1 } in the first argument of find().

However, you still need to decide how to deal with naming clashes because rename will clobber the target if the target exists.

#!/usr/bin/perl

use strict; use warnings;
use File::Find;

finddepth(\&process_file, $_) for @ARGV;
like image 151
Sinan Ünür Avatar answered Nov 14 '22 13:11

Sinan Ünür


if you are open to other approaches, here's a Python solution

import os
for R,DIR,FILES in os.walk("/mypath",topdown=False):
    for file in FILES:
        newfile=file.lower().replace(" ","_")
        new_file_name=os.path.join(R,newfile)
        os.rename( os.path.join(R,file) , new_file_name)
    for dir in DIR:
        newdir=dir.lower().replace(" ","_")
        new_dir_name=os.path.join(R,newdir)
        os.rename( os.path.join(R,dir) , new_dir_name)
like image 44
ghostdog74 Avatar answered Nov 14 '22 13:11

ghostdog74