Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change the case of filenames in Perl?

Tags:

filenames

perl

I'm trying to create a process that renames all my filenames to Camel/Capital Case. The closest I have to getting there is this:

perl -i.bak -ple 's/\b([a-z])/\u$1/g;' *.txt # or similar .extension.

Which seems to create a backup file (which I'll remove when it's verified this does what I want); but instead of renaming the file, it renames the text inside of the file. Is there an easier way to do this? The theory is that I have several office documents in various formats, as I'm a bit anal-retentive, and would like them to look like this:

New Document.odt
Roffle.ogg
Etc.Etc
Bob Cat.flac
Cat Dog.avi

Is this possible with perl, or do I need to change to another language/combination of them?

Also, is there anyway to make this recursive, such that /foo/foo/documents has all files renamed, as does /foo/foo/documents/foo?


2 Answers

You need to use rename .

Here is it's signature:


rename OLDNAME,NEWNAME

To make it recursive, use it along with File::Find


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

#default searches just in current directory
my @directories = (".");

find(\&wanted,  @directories);

sub wanted {
  #renaming goes here
}

The following snippet, will perform the code inside wanted against all the files that are found. You have to complete some of the code inside the wanted to do what you want to do.

EDIT: I tried to accomplish this task using File::Find, and I don't think you can easily achieve it. You can succeed by following these steps :

  • if the parameter is a dir, capitalize it and obtain all the files

  • for each file, if it's a dir, go back at the beginning with this file as argument

  • if the file is a regular file, capitalize it

Perl just got in my way while writing this script. I wrote this script in ruby :


require "rubygems"
require "ruby-debug"

# camelcase files

class File
    class << self
        alias :old_rename :rename
    end

    def self.rename(arg1,arg2)
        puts "called with #{arg1} and #{arg2}"
        self.old_rename(arg1,arg2)
    end
end

def capitalize_dir_and_get_files(dir)
    if File.directory?(dir)
        path_c          = dir.split(/\//)
        #base           = path_c[0,path_c.size-1].join("/")
        path_c[-1].capitalize!  
        new_dir_name    = path_c.join("/")
        File.rename(dir,new_dir_name)
        files = Dir.entries(new_dir_name) - [".",".."]
        files.map! {|file| File.join(new_dir_name,file)}
        return files 
    end
    return []
end

def camelize(dir)
    files = capitalize_dir_and_get_files(dir)
    files.each do |file|
        if File.directory?(file)
            camelize(file.clone)
        else
            dir_name    = File.dirname(file)
            file_name   = File.basename(file)
            extname     = File.extname(file)
            file_components = file_name.split(/\s+/)
            file_components.map! {|file_component| file_component.capitalize}           
            new_file_name = File.join(dir_name,file_components.join(" "))
            #if extname != ""
            #   new_file_name += extname
            #end
            File.rename(file,new_file_name)
        end
    end
end

camelize(ARGV[0])

I tried the script on my PC and it capitalizes all dirs,subdirs and files by the rule you mentioned. I think this is the behaviour you want. Sorry for not providing a perl version.

like image 91
11 revs, 2 users 99%Tempus Avatar answered Dec 07 '25 20:12

11 revs, 2 users 99%Tempus


Most systems have the rename command ....

NAME rename - renames multiple files

SYNOPSIS rename [ -v ] [ -n ] [ -f ] perlexpr [ files ]

DESCRIPTION "rename" renames the filenames supplied according to the rule specified as the first argument. The perlexpr argument is a Perl expression which is expected to modify the $_ string in Perl for at least some of the filenames specified. If a given filename is not modified by the expression, it will not be renamed. If no filenames are given on the command line, filenames will be read via standard input.

   For example, to rename all files matching "*.bak" to strip the extension, you might say

           rename 's/\.bak$//' *.bak

   To translate uppercase names to lower, you’d use

           rename 'y/A-Z/a-z/' *

OPTIONS -v, --verbose Verbose: print names of files successfully renamed.

   -n, --no-act
           No Action: show what files would have been renamed.

   -f, --force
           Force: overwrite existing files.

AUTHOR Larry Wall

DIAGNOSTICS If you give an invalid Perl expression you’ll get a syntax error.


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!