2009-03-24 3 views
2

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

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?

+0

Вы не указали, какие у вас есть текущие формы. – Axeman

ответ

9

Необходимо использовать rename.

Вот это подпись:


rename OLDNAME,NEWNAME 

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

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

EDIT: Я попытался выполнить эту задачу, используя File :: Find, и я не думаю, что вы можете легко ее достичь. Вы можете добиться успеха, выполнив следующие действия:

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

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

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

Perl только что на моем пути во время написания этого сценария. Я написал этот сценарий в рубине:


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]) 

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

+0

http://search.cpan.org/dist/File-Find-Rule/lib/File/Find/Rule.pm лучше, чем File :: Find, но YMMV. – ephemient

+0

Я очень вырос, используя File :: Find :). Мне нравится больше. – Geo

+0

Глобальный символ «@directories» требует явного имени пакета в строке bob.pl 5. Выполнение bob.pl отменено из-за ошибок компиляции. Пытался запустить bob.pl (с последним редактированием)^- результат. –

3

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

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

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

+0

В отличие от файловых систем BSD, однако, по умолчанию HFS + OS X не учитывает регистр. У меня нет Mac рядом, чтобы проверить, работают ли переименования только для случая ... – ephemient

+0

Неверное переименование только по умолчанию на томе HFS + по умолчанию на Mac (10.5) не работает: «$ touch x && mv x X mv:' x 'и 'X' - это тот же файл« –

1

Я бы просто использовал команду 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/;")"' \ 
       {} \; 

Cryptic, но он работает.

+0

StackOverflow не разрешает комментарии с менее чем 10 символами. Все, что я хотел сказать: + 1, выродка. – Geo

+0

Я смущен, что написал это. – ashawley

5

Большинство систем имеют команды переименования ....

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

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

ОПИСАНИЕ «переименовать» переименовывает имена файлов, предоставленные в соответствии с правилом, указанным в качестве первого аргумента. Аргумент 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. 

АВТОР Larry Wall

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

1

Еще один:

find . -type f -exec perl -e' 
    map { 
     ($p, $n, $s) = m|(.*/)([^/]*)(\.[^.]*)$|; 
     $n =~ s/(\w+)/ucfirst($1)/ge; 
     rename $_, $p . $n . $s; 
     } @ARGV 
    ' {} + 
0

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

Смежные вопросы