Copying files and changing their names

S

SamF

Hi all,

I have a directory with numerous folders, each of which contains
numerous folders and/or files.

Each of the files in each of these folders has a number. I want to
iterate through all these files, and, for every file that ends in a
'[filename]-9', I want to COPY the file and rename it
'[filename]-final'.

Is there a simple way to do this in Ruby?

Any help much appreciated!
Sam
 
S

Stefano Crocco

Alle mercoled=C3=AC 14 marzo 2007, SamF ha scritto:
Hi all,

I have a directory with numerous folders, each of which contains
numerous folders and/or files.

Each of the files in each of these folders has a number. I want to
iterate through all these files, and, for every file that ends in a
'[filename]-9', I want to COPY the file and rename it
'[filename]-final'.

Is there a simple way to do this in Ruby?

Any help much appreciated!
Sam

NOT TESTED - make a trial with some useless directory before using it on re=
al=20
data

require 'find'
require 'fileutils'

=46ind.find('.') do |f|
FileUtils.cp(f,f.sub(/-9$/, '-final')) if File.file?(f) and f.match /-9$/)
end

=46ind.find calls the block passing the name of each file or directory it=20
contains, recursively. In the block, we use the FileUtils.cp method to copy=
f=20
to the file whose name is obtained by rmoving the final -9 and adding -fina=
l,=20
but only if the name is the name of a file (not of a directory) and if the=
=20
name ends with -9.

I hope this helps

Stefano
 
S

Sam Fent

Stefano said:
NOT TESTED - make a trial with some useless directory before using it on
real
data

Hi Stefano (anzi, 'ciao!'),

Thank you very much -- that has helped me tremendously. I have one
further question though. What if, instead of the number "9", I wanted to
copy the file with the HIGHEST number.

For example, my files might be

example1.txt
example2.txt
test1.txt
test2.txt
test3.txt

If I wanted to change example2.txt to example-final.txt, and test3.txt
to test-final.txt, how could I iterate throught the files to find the
file with the highest number?

Grazie mille per qualsiasi aiuto,
Sam
 
S

Sam Fent

Sam said:
If I wanted to change example2.txt to example-final.txt, and test3.txt
to test-final.txt, how could I iterate throught the files to find the
file with the highest number?

Ok, so I worked it out myself, as I probably should have from the
beginning.

This is almost certainly not the most efficient code, in that it
iterates over the same directories several times, but here it is, in
case any future person wants to do the same thing (or any present person
wants to make it more efficient).

require 'find'
require 'fileutils'

usedNames = []

Find.find('.') do |f|
if (File.file?(f) and f.match(/txt$/))
name = f[/.*V/][0..-2]
if (!usedNames.include?(name))
usedNames += [name]
versions = []

# find the latest version number
Find.find('.') do |f|
if (File.file?(f) and f.match(/#{name}.*txt$/))
versionNumber = f[name.length+1..-5]
versions += [versionNumber]
end
end
versions = versions.sort
lastVersionNumber = versions[versions.length-1]

# copy file and re-name it FINAL
if (!lastVersionNumber.match(/.*FINAL.*/))
Find.find(name+"V"+lastVersionNumber+".txt") do |g|
puts "Changing file " + g + " to: " +
g.sub(/#{lastVersionNumber}/,"_FINAL")
FileUtils.cp(g,g.sub(/#{lastVersionNumber}/,"FINAL"))

end
end
end
end
end
 
S

Stefano Crocco

Alle mercoled=C3=AC 14 marzo 2007, Sam Fent ha scritto:
Hi Stefano (anzi, 'ciao!'),

Thank you very much -- that has helped me tremendously. I have one
further question though. What if, instead of the number "9", I wanted to
copy the file with the HIGHEST number.

For example, my files might be

example1.txt
example2.txt
test1.txt
test2.txt
test3.txt

If I wanted to change example2.txt to example-final.txt, and test3.txt
to test-final.txt, how could I iterate throught the files to find the
file with the highest number?

Grazie mille per qualsiasi aiuto,
Sam

This should work:

require 'find'
require 'set'
require 'file_utils'

=46ind.find('.') do |f|
# consider only directories, we'll take care of files later=09
if File.directory?(f)
# create a Set containing the names of the files in the directory f [1]
entries=3DSet.new(Dir.entries(f).reject{|e| File.directory?(e)})
#separate the files basing on their basename (the part before -number) =
[2]
names=3Dentries.classify{|e| e.match(/^.*-\d+$/)[1]}
# for each of the basenames
names.each_value do |v|
# sort the set basing on the number and select the last
name=3Dv.sort_by{|n| n.match(/-(\d+)/)[1].to_i}.last
# copy it to the new name. name is relative to f, so we prepend it
FileUtils.cp "#{f}#{name}", "#{f}#{name.sub(/-\d+$/, '-final')}"
end
end
end

The line marked by [2] creates a hash of sets, each of them containing the=
=20
files with the same basename. This method is the only reason to use a set i=
n=20
line [1], instead of keeping the array. For instance, if the directory f=20
contains the files
a-1
a-2
a-3
b-1
b-2
c-1
c-2
c-3
c-4

the result of line [2] will be a hash with keys 'a', 'b' and 'c'. The keys =
'a'=20
will contain a set with elements 'a-1', 'a-2', 'a-3', and so on for the oth=
er=20
keys.

Stefano
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top