2015-04-29 3 views
1

У меня есть много каталогов с именами файлов с именами txt. Я хочу сделать копии файлов txt, переименовать их в соответствии с содержащим их каталогом, а затем переместить их в родительский каталог (который является каталогом, в котором хранятся исходные файлы txt, обозначенные как «txts» в скрипте ниже). Я хочу сохранить исходные файлы txt с их оригинальными именами в своих исходных каталогах, так что ничего в исходных каталогах не изменится.Как скопировать файлы и переименовать их в соответствии с их исходными каталогами с помощью Ruby?

У меня есть старый сценарий, который я думаю, что достигнуто (некоторые) мои цели один раз, возможно перемещение вместо копирования оригинальных текстовые файлы, но я не могу запустить его успешно в настоящее время:

require 'find' 
require 'fileutils' 

Find.find("txts") do |path| 
    if FileTest.directory?(path) 
    next 
    end 

    ret = path.scan(/.*txts\/([^\/]+)\/.*/) 
    name = ret[0].to_s + ".txt" 
    FileUtils.mv(path, name) 
end 

лет назад друг написал это и успешно провел его из среды unix. Когда я запускаю его сейчас, возвращается огромное количество ошибок. Я использую Ruby 2.2.2, и вполне возможно, что где-то есть местозаполнитель, который я слишком новичок, чтобы узнать, или, возможно, что-то изменилось из старой версии FileUtils ... Я действительно не знаю и боюсь, что я был не в состоянии получить ответы на мои навыки неофита.

И поэтому я обращаюсь к вам ...

Edit: Вот сообщение об ошибке:

C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1328:in `stat': Invalid argument @ rb_file 
_s_stat - ["may2013"].txt (Errno::EINVAL) 
     from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1328:in `lstat' 
     from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1247:in `exist?' 
     from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:519:in `block in mv' 
     from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1570:in `block in fu_each_src 
_dest' 
     from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1586:in `fu_each_src_dest0' 
     from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1568:in `fu_each_src_dest' 
     from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:516:in `mv' 
     from extracttxt.rb:12:in `block in <main>' 
     from C:/Ruby22/lib/ruby/2.2.0/find.rb:48:in `block (2 levels) in find' 
     from C:/Ruby22/lib/ruby/2.2.0/find.rb:47:in `catch' 
     from C:/Ruby22/lib/ruby/2.2.0/find.rb:47:in `block in find' 
     from C:/Ruby22/lib/ruby/2.2.0/find.rb:42:in `each' 
     from C:/Ruby22/lib/ruby/2.2.0/find.rb:42:in `find' 
     from extracttxt.rb:6:in `<main>' 
+0

Пожалуйста, разместите сообщение об ошибке. –

+0

Добавлен в тему. Благодарю. – rufus

ответ

0

Сообщение об ошибке показывает, что ret[0] является массив [ "may13" ], поэтому ret[0].to_s + ".txt" вычисляется в строке ["may13"].txt. Я не уверен, но возможно изменение String#scan в Ruby 1.9 или 2.0, поэтому он возвращает массив массивов при наличии захватов, тогда как перед ним возвращается массив строк.

Нечто подобное должно решить эту проблему:

require 'find' 
require 'fileutils' 

Find.find("txts") do |path| 
    if FileTest.directory?(path) 
    next 
    end 

    if path =~ %r{txts/([^/]+)/} 
    FileUtils.cp(path, "#{$1}.txt") 
    end 
end 

Если вы хотите, чтобы соответствовать по расширению файла вы можете либо добавить его к Regexp выше (например, %r{txts/([^/]+)/.+\.txt$}) или вы можете использовать Dir[] (ака Dir.glob) например:

require 'dir' 
require 'fileutils' 

Dir['txts/**/*.txt'].each do |path| 
    next if FileTest.directory?(path) || 
    next unless path =~ %r{txts/([^/]+)/} 

    FileUtils.cp(path, "#{$1}.txt") 
end 

Я не знаю, будет ли разница в производительности, но, возможно, стоит попробовать.

+0

Это замечательно. Спасибо! Я изменил его, чтобы использовать FileUtils.cp, чтобы сохранить содержимое исходных каталогов. Однако это неожиданно приводит к серьезному раздуванию ресурсов. Судя по времени, которое требуется для завершения операций, все содержимое каталогов добавляется в массив. Вывод в каталоге txts предназначен, как и предполагалось, но только для новых файлов txt. Есть ли способ, чтобы мы могли быть более избирательными при построении массива? – rufus

+0

Более избирательно, каким образом? Вы говорите «не только файлы txt ... но и остальные данные», но исходный скрипт не я различаю между различными типами файлов. Можете ли вы объяснить, какие файлы вы хотите скопировать, а какие нет? –

+0

Результат, полученный вашим скриптом, - именно то, что я хочу. Только txts копируются в родительский каталог \ txts. Однако, когда я изменил FileUtils.mv на FileUtils.cp, время обработки значительно увеличилось, а каталоги, которые занимают самое длинное время для копирования txt, - это те, у которых наибольшее количество случайных дополнительных данных. Это заставляет меня думать, что ВСЕ данные копируются, причем данные, отличные от txt, удаляются, когда операция завершается, оставляя только нужные txts в каталоге \ txts. Это не сделка, но неэффективная и приведет к очень длительным операциям ... – rufus