Как я могу изменить регистр имен файлов в Perl? - PullRequest
2 голосов
/ 24 марта 2009

Я пытаюсь создать процесс, который переименовывает все мои имена файлов в Camel / Capital Case. Самое близкое, что я должен получить, это:

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

Который, кажется, создает файл резервной копии (который я удалю, когда проверю, это делает то, что я хочу); но вместо переименования файла, он переименовывает текст внутри файла. Есть ли более простой способ сделать это? Теория состоит в том, что у меня есть несколько офисных документов в различных форматах, так как я немного антивеществен и хотел бы, чтобы они выглядели так:

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

Возможно ли это с помощью perl, или мне нужно перейти на другой язык / их комбинацию?

Кроме того, есть ли способ сделать это рекурсивным, например, чтобы / foo / foo / documents переименовали все файлы, как это делает / foo / foo / documents / foo?

Ответы [ 6 ]

9 голосов
/ 24 марта 2009

Вам необходимо использовать переименовать .

Вот его подпись:


rename <strong>OLDNAME,NEWNAME</strong>

Чтобы сделать его рекурсивным, используйте его вместе с 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
}

Следующий фрагмент кода будет выполнять код внутри требуемого для всех найденных файлов. Вы должны завершить часть кода внутри wanted , чтобы сделать то, что вы хотите.

РЕДАКТИРОВАТЬ: я пытался выполнить эту задачу, используя File :: Find, и я не думаю, что вы можете легко достичь этого. Вы можете добиться успеха, выполнив следующие действия:

  • если параметр является dir, используйте его заглавные буквы и получите все файлы

  • для каждого файла, если это каталог, вернитесь в начало с этим файлом в качестве аргумента

  • если файл является обычным файлом, используйте заглавные буквы

Perl только мешал мне при написании этого сценария. Я написал этот скрипт на 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])

Я попробовал скрипт на моем ПК, и он прописал все каталоги, подкаталоги и файлы по правилу, которое вы упомянули. Я думаю, что это поведение, которое вы хотите. Извините, что не предоставил версию Perl.

5 голосов
/ 25 марта 2009

В большинстве систем есть команда переименования ....

NAME переименовать - переименовывает несколько файлов

СИНТАКСИС переименовать [-v] [-n] [-f] perlexpr [файлы]

ОПИСАНИЕ «rename» переименовывает имена файлов, предоставленные в соответствии с правилом, указанным в качестве первого аргумента. Аргумент perlexpr - это выражение Perl, которое как ожидается, изменит строку $ _ в Perl, по крайней мере, для некоторых из указанных имен файлов. Если данное имя файла не изменено выражением, оно не будет переименовано. Если в командной строке не указано ни одного имени файла, оно будет прочитано через стандартный ввод.

   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/' *

ВАРИАНТЫ -v, --verbose Подробно: выводить имена файлов, успешно переименованных.

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

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

АВТОР Ларри Уолл

ДИАГНОСТИКА Если вы введете недопустимое выражение Perl, вы получите синтаксическую ошибку.

3 голосов
/ 24 марта 2009

Поскольку Perl прекрасно работает на нескольких платформах, позвольте мне предупредить вас, что файловые системы FAT (и FAT32, и т. Д.) Будут игнорировать переименования, которые только изменяют регистр имени файла. Это верно для Windows и Linux и, вероятно, верно для других платформ, которые поддерживают файловую систему FAT.

Таким образом, в дополнение к ответу Geo , обратите внимание, что вам, возможно, придется фактически изменить имя файла (например, добавив символ в конец), а затем изменить его обратно на нужное имя с правильным регистром.

Если вы будете переименовывать файлы только в файловых системах NTFS или только в файловых системах ext2 / 3/4 (или в других файловых системах UNIX / Linux), вам, вероятно, не нужно беспокоиться об этом. Я не знаю, как работает файловая система Mac OSX, но, поскольку она основана на BSD, я предполагаю, что она позволит вам переименовывать файлы, только изменяя регистр имени.

1 голос
/ 25 марта 2009

Еще один:

find . -type f -exec perl -e'
  map {
        ( $p, $n, $s ) = m|(.*/)([^/]*)(\.[^.]*)$|;
        $n =~ s/(\w+)/ucfirst($1)/ge;
        rename $_, $p . $n . $s;
      } @ARGV
  ' {} +
1 голос
/ 24 марта 2009

Я бы просто использовал команду find для повторения подкаталогов и mv для переименования, но все же использовал Perl для правильного переименования.

find /foo/foo/documents -type f \
     -execdir bash -c 'mv "$0" \
                          "$(echo "$0" \
                              | perl -pe "s/\b([[:lower:]])/\u\$1/g; \
                                          s/\.(\w+)$/.\l\$1/;")"' \
              {} \;

Загадочно, но работает.

0 голосов
/ 25 марта 2009

Имейте в виду, что в файловых системах с запоминанием регистра (FAT / NTFS) вам необходимо сначала переименовать файл во что-то другое, а затем в изменение регистра. Прямое переименование из «etc.etc» в «Etc.Etc» не удастся или будет проигнорировано, поэтому вам нужно будет сделать два переименования: «etc.etc» в «etc.etc ~» затем «etc.etc ~» например "Etc.Etc".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...