Copying all Files with New Name

Hi,
This forum has already been very helpful , Many Thanks.

Problem: I actually want to copy the contents of all files that is in a
particular directory into a new directory.The new files should be of a
specific size (2MB)and each with a new name (randomly assigned).

My Current Code looks,

require ‘ftools’
testdir = “K:/test”

Iterating over each entry

Dir.entries(testdir).each do |file|

Joining the path where the files are

path = File.join testdir, file
if File.file? path

      File.open path
      File.copy(file,'K:/t1') # NOTE: t1 file doesn't exist assuming

will create itself? probably wrong

  end
 end

end

When simply trying to copy using File.copy(to,from) it gives following
error message “No such file or directory K:/”

Do you think this approach is completely wrong and I should try
creating File.new and reading every single line and copying over?

Any suggestions about giving random names for the new files…?

Many Thanks,

Problem: I actually want to copy the contents of all files that is in a
particular directory into a new directory.The new files should be of a
specific size (2MB)and each with a new name (randomly assigned).

My Current Code looks,

require ‘ftools’

I recommend using ‘fileutils’ instead. From the ftools docs:
“FileUtils contains all or nearly all the same functionality and more,
and is a recommended option over ftools”

testdir = “K:/test”

Iterating over each entry

Dir.entries(testdir).each do |file|

Okay within this context you’ll probably need to “filter out” or
ignore the “.” and “…” entries. They show up in windows too.

Dir.entries(testdir).reject { |d| %w{. …}.include?(d) }.each do
|file| # example removes . and …

Joining the path where the files are

path = File.join testdir, file
if File.file? path

     File.open path

You don’t need to “open” the file to copy it, whether you’re using
ftools or fileutils. I’d nuke the “File.open path” line.

     File.copy(file,'K:/t1') # ...

This is likely failing when you’re trying to copy directory entries
“.” and “…” which expanded would look like:

File.copy(‘K:/test/.’, ‘K:/t1’)

However, if you filter out these entries beforehand then this should
work. Also note that it will create ‘K:/t1’ if it doesn’t exist and
will also overwrite it if it does (unless there is a
permissions/access issue). The fileutils equivalent would be:

FileUtils.cp(file, ‘K:/t1’)

 end

end
end

Is it just me? I think I cound 1-too-many “ends” there.

When simply trying to copy using File.copy(to,from) it gives following
error message “No such file or directory K:/”

Again, I suspect this is because of the “.” or “…” entry being
“copied”. File.copy only allows the source to be a file, not a
directory (or so it appears).

Do you think this approach is completely wrong and I should try
creating File.new and reading every single line and copying over?

No need to use File.new. File.copy or FileUtils.cp do this for you just
fine.

Any suggestions about giving random names for the new files…?

If you’re not worried about race conditions here is a simple version
from one of my old projects.

def unique_filename(location, basename = ‘’, extension = nil, digits =
4)
extension = extension ? “.#{extension}” : ‘’
index = 0
namer = lambda { “#{basename}#{index.to_s.rjust(digits,
‘0’)}#{extension}” }
name = namer.call
while File.exists?(File.join(location, name))
index += 1
name = namer.call
end
File.join(location, name)
end

Example Usage:

require ‘fileutils’
source = “K:/test”
dest = “K:”
Dir.entries(source).reject { |d| %w{. …}.include?(d) }.each do |file|
FileUtils.cp(File.join(source, file), unique_filename(dest))
end

Thanks so much , I’ll all and will get back to you.

Many Thanks,
Gear,

Thanks very much , all worked very well. I can now,

  • Copy all files from a directory with a new name to the required
    destination.

I would appreciate if you can give some suggestions regarding the
following,

Problem: Defining a specific File Size when copying over, say of size=
2MB
For example if source file size is = 20MB, I want to get total of 10
files of size 2MB.

Something like,
# when copying if file.size > 2MB “Stop”
AND
# Create a new file
again when copying if file.size > 2MB “Stop”
# Create a new file
# And so on…

Probably,dividing the file size by 2 and then creating that many files
to copy the contents over
so if file.size = 20
total files = 20/2

Also the most difficult thing for me is how to keep track of what data
has been copied over already ?

Something like,
# Create a new file if size > 2MB
# AND Copy the data from the point onwards.

I hope that I have explained well what I actually want to achieve.

Any suggestions would be much appreciated including any methods in ruby
any common tricks for doing the above?

The Current Code i am using isn’t intelligent it copies over an entire
file regardless of the file size,

Works perfectly fine,

def unique_filename(location, basename = ‘’, extension = ‘.txt’, digits
= 4)

Initializing file extension

extension = extension ? “.#{extension}” : ‘’
index = 0
namer = lambda {
“#{basename}#{index.to_s.rjust(digits,‘0’)}#{extension}” }
name = namer.call
while File.exists?(File.join(location, name))
index = index + 1
name = namer.call
end
File.join(location, name)
end

Many Thanks,
Gear