Ruby: Copy contents of folder in zipfile - ruby

There is a zipfile. It can either have 10 files or one folder. This folder will have the 10 files. Now, if the zipfile has a folder, then i have to move all the files one directory above i.e.
zipfile.zip has folder. folder has 10 files. normally, if i unzip, i get zipfile/folder/10files. Now, I have to get like zipfile/10files. ie. move all the files one directory above.
How to do this? Please help.

If you don't mind using Linux unzip and really aren't worried about subdirectories:
def unzip(file)
to = File.join(File.dirname(file), File.basename(file, ".*"))
Dir.mkdir(to) unless File.exists?(to)
`unzip -j #{file} -d #{to}`
end
# unzip('yourfile.zip')
This method creates a new directory in the same directory as the zip file with the same name as the zipfile (minus extension). It then extracts (using unzip) the zip file into that directory, ignoring all paths (the -j flag tells unzip to junk paths).
EDIT
Per your comment, here is a way to do it without system calls:
def unzip(file)
Zip::ZipFile.open(file) do |zipfile|
to = File.join(File.dirname(file), File.basename(file, ".*"))
FileUtils.mkdir(to) unless File.exists? to
zipfile.each do |f|
if f.file? # Don't extract directories
fpath = File.join(to, File.basename(f.name))
zipfile.extract(f, fpath) unless File.exists?(fpath)
end
end
end
end

Related

TarWriter help adding multiple directories and files

The code in this question works, but only with a single directory. I can also make it output a file archive as well. But not both a file and a directory, or two directories. I am hoping to make it work with a list of paths, including directories and files that are all placed in the same archive. If I try to add more than one path, the tarfile becomes corrupted. I thought I could continue adding files/data to archive as long as the TarWriter object is open.
QUESTION: In addition to how I can make the above example work with multiple paths (in linked post), can someone please help explain how files and directories are added into an archive? I have looked at the directory structure/format, but I can't seem to understand why this wouldn't work with more than one directory/file.
You can add multiple paths to Dir object
Dir[File.join(path1, '**/*'), File.join(path2, '**/*')]
After which the code would be something like this:
BLOCKSIZE_TO_READ = 1024 * 1000
def create_tarball(path)
tar_filename = Pathname.new(path).realpath.to_path + '.tar'
File.open(tar_filename, 'wb') do |tarfile|
Gem::Package::TarWriter.new(tarfile) do |tar|
Dir[File.join(path1, '**/*'), File.join(path2, '**/*')].each do |file|
mode = File.stat(file).mode
relative_file = file.sub(/^#{ Regexp.escape(path) }\/?/, '')
if File.directory?(file)
tar.mkdir(relative_file, mode)
else
tar.add_file(relative_file, mode) do |tf|
File.open(file, 'rb') do |f|
while buffer = f.read(BLOCKSIZE_TO_READ)
tf.write buffer
end
end
end
end
end
end
end
tar_filename
end

copy contents of a folder from one location to another using ruby

I wrote this code to copy files from one location to another, but I want to copy the contents of the entire folder to a target location.
How do I do this? I tried file.copy dir, but it doesn't work.
require 'ftools'
fname = gets.chomp
if fname == "android" then
File.copy "/Volumes/TempData/Collects/Sasi/android/grade.rb","/Volumes/Data"
elsif fname == "ios" then
File.copy"/Volumes/Sasi/ios/grade.rb","/Volumes/TempData/Sasi/KugaViewr/grade.rb"
else
puts "do nothing"
end
FileUtils#copy_entry will be the good choice for this thing.
Copies a file system entry src to dest. If src is a directory, this method copies its contents recursively. This method preserves file types, c.f. symlink, directory... (FIFO, device files and etc. are not supported yet)
From the pickaxe (1.8), p 681:
The FileUtils library is now recommended over ftools.
If you have to use ftools for some reason, see ftools solution.

How do I make a Ruby script to move .mp3 files to iTunes folder?

In order to get my music into iTunes, I have to find its location and then I have to dig into my files to find my iTunes folder and copy/paste it into my iTunes folder.
What I want is a Ruby script that will scan the folder that it is in for files that end in .mp3 and then move those files into my iTunes folder.
I know how to move the files into iTunes if I know the name of the file, however, how can I find only the .mp3 files to my iTunes folder. I just need some direction into what I can use to only select files ending with .mp3.
require 'find'
require 'fileutils'
Find.find('/') do |f|
FileUtils.mv(f, "ABSOLUTE PATH TO ITUNESFOLDER") if f.match(/\.mp3\Z/)
end
This will probably take a while as it will scan the entire directory tree of it's start point, in this case '/' (the entire file system). Maybe start in your home directory instead of '/'
You can use this recursive method to find files in many directories and move them to your itunes folder.
def ls_R(dirname)
Dir.foreach(dirname) do |dir|
dirpath = dirname + '/' + dir
if File.directory?(dirpath)
if dir != '.' && dir != '..'
ls_R(dirpath)
end
else
FileUtils.mv(dirpath, "PATH_TO_ITUNESFOLDER") if dirpath.match(/\.mp3\Z/)
end
end
end
A remark to both solutions offered above:
there is a "add automatically to itunes" folder which you should target
for this type of action.
....../iTunes/iTunes Media/Automatically Add to iTunes/
This allows for a better way to get your tracks in iTunes.

Delete hidden files in Ruby

Does anyone know how to delete all files in a directory with Ruby. My script works well when there are no hidden files but when there are (i.e .svn files) I cannot delete them and Ruby raises the Errno::ENOTEMPTY error.
How do I do that ?
If you specifically want to get rid of your svn files, here's a script that will do it without harming the rest of your files:
require 'fileutils'
directories = Dir.glob(File.join('**','.svn'))
directories.each do |dir|
FileUtils.rm_rf dir
end
Just run the script in your base svn directory and that's all there is to it (if you're on windows with the asp.net hack, just change .svn to _svn).
Regardless, look up Dir.glob; it should help you in your quest.
.svn isn't a file, it's a directory.
Check out remove_dir in FileUtils.
It probably has nothing to do with the fact, that .svn is hidden. The error suggest, that you are trying to delete a non empty directory. You need to delete all files within the directory before you can delete the directory.
Yes, you can delete (hiden) directory using FileUtils.remove_dir path.
I happend to just write a script to delete all the .svn file in the directory recursively. Hope it helps.
#!/usr/bin/ruby
require 'fileutils'
def svnC dir
d = Dir.new(dir)
d.each do |f|
next if f.eql?(".") or f.eql?("..")
#if f is directory , call svnC on it
path = dir + "/" + "#{f}"
if File.stat(path).directory?
if f.eql?(".svn")
FileUtils.remove_dir path
else
svnC path
end
end
end
end
svnC FileUtils.pwd
As #evan said you can do
require 'fileutils'
Dir.glob('**/.svn').each {|dir| FileUtils.rm_rf(dir) }
or you can make it a one liner and just execute it from the command line
ruby -e "require 'fileutils'; Dir.glob('**/.svn').each {|dir| FileUtils.rm_rf(dir) }"

RubyZip - files from different directories have path in zip

I'm trying to use RubyZip to package up some files. At the moment I have a method which happily zips on particular directory and sub-directories.
def zip_directory(zipfile)
Dir["#{#directory_to_zip}/**/**"].reject{|f| reject_file(f)}.each do |file_path|
file_name = file_path.sub(#directory_to_zip+'/','');
zipfile.add(file_name, file_path)
end
end
However, I want to include a file from a completely different folder. I have a the following method to solve this:
def zip_additional(zipfile)
additional_files.reject{|f| reject_file(f)}.each do |file_path|
file_name = file_path.split('\\').last
zipfile.add(file_name, file_path)
end
end
While the file is added, it also copies the directory structure instead of placing the file at the root of the folder. This is really annoying and makes it more difficult to work with.
How can I get around this?
Thanks
Ben
there is setting to include (or exclude) the full path for zip libraries, check that setting
Turns out it was because the filename had the pull path in. My split didn't work as the path used a / instead of a . With the path removed from the filename it just worked.

Resources