Copy Folder Contents to Parent Directory in Rake (on Windows) - ruby

I have a set of files in a folder ../SomeFolder/AndAnother/dist
the dist folder contains a bunch of files and folders that I want to move up a level in a Rake task.
So
../SomeFolder/AndAnother/dist/subFolder/a.txt becomes ../SomeFolder/AndAnother/subFolder/a.txt
I can do this on linux by
task :lift_to_parent do
sh('mv', '../SomeFolder/AndAnother/dist/*', '../SomeFolder/AndAnother')
end
but this Rake task also runs on Windows and on that OS i get Errno::EACCES: Permission denied # unlink_internal
I'm hoping that FileUtils.mv will work on both linux and windows...
but if I
task :lift_to_parent do
FileUtils.mv '../SomeFolder/AndAnother/dist', '../SomeFolder/AndAnother', :force => true
end
I get ArgumentError: same file: ../SomeFolder/AndAnother/dist and ../SomeFolder/AndAnother/dist so I'm clearly missing something to allow FileUtils.mv to copy up a level (or going about this the wrong way)
So, how do I fix my FileUtils version or otherwise use a Rake task to copy a folder structure to its parent?

I've ended up doing this
task : lift_to_parent do
copied_by_jenkins = '../SomeFolder/AndAnother/dist'
copy_pattern = "#{copied_by_jenkins}/**/*"
target_directory = '../SomeFolder/AndAnother/Public'
next unless File.exists? copied_by_jenkins
FileList[copy_pattern].each do |file|
file_path = File.dirname(file).sub! copied_by_jenkins, ''
file_name = File.basename(file)
target_directory = File.join(target_directory, file_path)
destination = File.join(target_directory, file_name)
FileUtils.mkdir_p target_directory
FileUtils.copy_file(file, destination) unless File.directory? file
end
FileUtils.remove copied_by_jenkins
end
but that seems like a lot of the typing to achieve my goal

Related

Rake get directory name in file glob

If a Rake File exists with the following code:
file 'assets/*/map.a' => ['map.b', 'map.c'] do
# Code goes here...
end
I want to know what the name of the directory in the glob is (instead of the file). Any suggestions?
file 'assets/*/map.a' => ['map.b', 'map.c'] do |path|
File.basename(File.dirname(path))
end

Ruby - FileUtils copy_file Permission denied on Windows

I'm making gem that copy files from /template directory (inside the gem) into the current directory of the console.
Here's what it looks like:
require "fileutils"
# Get the console's current directory
destination_dir = Dir.pwd
# Home directory of my gem, looks like C:/Ruby193/lib/ruby/gems/1.9.1/gems/my_gem-1.0.0
home_dir = File.expand_path( "..", File.dirname(__FILE__) )
# Template directory, looks like C:/Ruby193/lib/ruby/gems/1.9.1/gems/my_gem-1.0.0/template
template_dir = File.join( home_dir, "template" )
FileUtils.copy_file( template_dir, destination_dir )
And I got this error:
C:/Ruby193/lib/ruby/1.9.1/fileutils.rb:1370:in `initialize': Permission denied -
C:/Ruby193/lib/ruby/gems/1.9.1/gems/my_gem-1.0.0/template (Errno::
EACCES)
I have checked that the directory does exists by running Dir[template_dir].
Any solution? Thanks
UPDATE to answer comments below
#Babai
I added this line before copy_file, but still doesn't work. Am I doing it right?
FileUtils.chmod(0777, template_dir)
#mudasobwa
Here's the result of the code
# puts "#{template_dir} \n #{destination_dir}"
C:/Ruby193/lib/ruby/gems/1.9.1/gems/my_gem-1.0.0/template
C:/Users/myname/Documents/Test
My bad. My template directory contains another folders. So I need to use cp_r instead of copy_file
FileUtils.cp_r( template_dir, destination_dir )

Ruby - FileUtils.cp deletes file and fails

I am trying to copy a file in ruby using FileUtils#cp
Unfortunately, Ruby is deleting the file and then is unable to copy it because it is missing.
Is this a known bug or something I am doing wrong with the cp method.
src = "/var/tmp/myfile"
dest = "/usr/bin/myfile"
FileUtils.cp(src, dest)
It always complains that src file is missing but when I check it has been deleted. If I recreate the file and set permissions to 777 the file is present, after running the script it is gone and the copy fails
Place the following in a copy_myfile.rb, then run with: sudo ruby copy_myfile.rb
require 'fileutils'
src = "/var/tmp/myfile"
dest = "/usr/bin"
FileUtils.cp(src, dest)
It seems to work for me in Ruby 1.9.3:
my file permission: -rw-rw-r--
require 'fileutils'
=> true
irb(main):002:0> FileUtils.cp 'test.txt', 'text1.txt'
=> nil
The file does get copied.

Ruby NET::SCP containing Wildcard

I need to download a file daily from a client that I have SCP but not SSH access to.
The file name will always be /outgoing/Extract/visit_[date]-[timestamp].dat.gz'
For example yesterdays file was called visits_20130604-090003.dat.gz
I can not rely on the fact that the time stamp will always be the same, but the date should always be yesterdays date:
My set up so far:
My home directory contains to sub-directories named downloads_fullname and downloads_wildcard.
It also contains an simple ruby script named foo.rb.
The contents of foo.rb are this`
#! /usr/bin/ruby
require 'net/ssh'
require 'net/scp'
yesterday = (Time.now - 86400).strftime('%Y%m%d')
Net::SCP.start('hostname', 'username') do |scp|
scp.download!('/outgoing/Extract/visits_' + yesterday + '-090003.dat.gz', 'downloads_fullname')
scp.download!('/outgoing/Extract/visits_' + yesterday + '-*.dat.gz', 'downloads_wildcard')
end
When run the downloads_fullname directory contains the file, but the downloads_wildcard directory does not.
Is there any way to use wildcarding in Net::SCP? Or does anybody have any sly workarounds? I tried \*to no avail.
Thank you Tin Man!!!
To anybody else, here is the code I ended up with following Tin Man's lead:
(Tried to post it as a comment but had formatting issues)
#! /usr/bin/ruby
require 'net/sftp'
yesterday = (Time.now - 86400).strftime('%Y%m%d')
Net::SFTP.start('hostname', 'username') do |sftp|
sftp.dir.foreach("/outgoing/Extract") do |file|
if file.name.include? '_' + yesterday + '-'
sftp.download!('/outgoing/Extract/' + file.name, 'downloads/'+ file.name)
end
end
end
I don't think you can get there using scp because it expects you to know exactly which file you want, but sftp will let you get a directory listing.
You can use Net::SFTP to programmatically pick your file and request it. This is the example code:
require 'net/sftp'
Net::SFTP.start('host', 'username', :password => 'password') do |sftp|
# upload a file or directory to the remote host
sftp.upload!("/path/to/local", "/path/to/remote")
# download a file or directory from the remote host
sftp.download!("/path/to/remote", "/path/to/local")
# grab data off the remote host directly to a buffer
data = sftp.download!("/path/to/remote")
# open and write to a pseudo-IO for a remote file
sftp.file.open("/path/to/remote", "w") do |f|
f.puts "Hello, world!\n"
end
# open and read from a pseudo-IO for a remote file
sftp.file.open("/path/to/remote", "r") do |f|
puts f.gets
end
# create a directory
sftp.mkdir! "/path/to/directory"
# list the entries in a directory
sftp.dir.foreach("/path/to/directory") do |entry|
puts entry.longname
end
end
Based on that you can list the directory entries then use find or select to iterate over the returned list to find the one with the current date. Pass that filename to sftp.download! to download it to a local file.

Trouble Creating Directories with mkdir

New to Ruby, probably something silly
Trying to make a directory in order to store files in it. Here's my code to do so
def generateParsedEmailFile
apath = File.expand_path($textFile)
filepath = Pathname.new(apath + '/' + #subject + ' ' + #date)
if filepath.exist?
filepath = Pathname.new(filepath+ '.1')
end
directory = Dir.mkdir (filepath)
Dir.chdir directory
emailText = File.new("emailtext.txt", "w+")
emailText.write(self.generateText)
emailText.close
for attachment in #attachments
self.generateAttachment(attachment,directory)
end
end
Here's the error that I get
My-Name-MacBook-2:emails myname$ ruby etext.rb email4.txt
etext.rb:196:in `mkdir': Not a directory - /Users/anthonydreessen/Developer/Ruby/emails/email4.txt/Re: Make it Brief Report Wed 8 May 2013 (Errno::ENOTDIR)
from etext.rb:196:in `generateParsedEmailFile'
from etext.rb:235:in `<main>'
I was able to recreate the error - it looks like email4.txt is a regular file, not a directory, so you can't use it as part of your directory path.
If you switched to mkdir_p and get the same error, perhaps one of the parents named in '/Users/anthonydreessen/Developer/Ruby/emails/email4.txt/Re: Make it Brief Report Wed 8 May 2013' already exists as a regular file and can't be treated like a directory. Probably that last one named email.txt
You've got the right idea, but should be more specific about the files you're opening. Changing the current working directory is really messy as it changes it across the entire process and could screw up other parts of your application.
require 'fileutils'
def generate_parsed_email_file(text_file)
path = File.expand_path("#{#subject} #{date}", text_file)
while (File.exist?(path))
path.sub!(/(\.\d+)?$/) do |m|
".#{m[1].to_i + 1}"
end
end
directory = File.dirname(path)
unless (File.exist?(directory))
FileUtils.mkdir_p(directory)
end
File.open(path, "w+") do |email|
emailText.write(self.generateText)
end
#attachments.each do |attachment|
self.generateAttachment(attachment, directory)
end
end
I've taken the liberty of making this example significantly more Ruby-like:
Using mixed-case names in methods is highly irregular, and global variables are frowned on.
It's extremely rare to see for used, each is much more flexible.
The File.open method yields to a block if the file could be opened, and closes automatically when the block is done.
The ".1" part has been extended to keep looping until it finds an un-used name.
FileUtils is employed to makes sure the complete path is created.
The global variable has been converted to an argument.

Resources