I'm new to ruby. Actually I'm trying to create an empty file "myfile.txt" in each of the following directories:
../../../../../TESTS/Test_A/myTest_A/
../../../../../TESTS/Test_B/myTest_B/
../../../../../TESTS/Test_C/myTest_C/
../../../../../TESTS/Test_D/myTest_D/
As you can see, the name of the Top directory is "TEST" and than after this, every directory have a different name but starts with "Test_", and than each "Test_*" directory contains only one directory and there my file should go in. I'm trying something like this:
require 'pathname'
def create_myFile
pn = Pathname.new('../../../../../TESTS/Test_*/**')
myFile = File.new("#{pn}/myFile.txt", "w+")
end
create_myFile
It doesn't work. Any suggestions?
Pathname does not accept wildcards. Dir#[] does:
Dir['../../../../../TESTS/Test_*/**'].each do |dir|
File.new File.join(dir, 'myFile.txt'), 'w+'
end
Related
I have the following code to connect my rails app to my FTP. This works great. However, I want to use open-uri to open the csv file so I can parse it. Any ideas how to do this? I think it's an easy thing to do but I'm missing something.
require 'net/ftp'
ftp = Net::FTP.new
ftp.connect("xxx.xxx.xx.xxx",21)
ftp.login("xxxxx","xxxx")
ftp.chdir("/")
ftp.passive = true
puts ftp.list("TEST.csv")
You'll need to use #gettextfile.
A) Get the file to a local temporary file and read its content
# Creating a tmp file can be done differently as well.
# It may also be omitted, in which case `gettextfile`
# will create a file in the current directory.
Dir::Tmpname.create(['TEST', ['.csv']) do |file_name|
ftp.gettextfile('TEST.csv', file_name)
content = File.read(file_name)
end
B) Pass a block to gettextfile and get the content one line at a time
content = ''
ftp.gettextfile('TEST.csv') do |line|
content << line
end
I need to write a script in Ruby to rename all *.htm files to *.html in a given
directory.
I've been given a script with some pieces missing.
I need to "METHOD" with the appropriate method name and "REGEX" with an appropriate
regular expression to match all the files that end in .htm.
Dir.METHOD("*.htm").each do |html_file|
FileUtils.METHOD html_file, "#{html_file.METHOD(/REGEX/,'.html')}"
end
Does anyone know what I should replace "METHOD" and "REGEX" with?
Dir.glob("*.htm") do |html_file|
FileUtils.mv(html_file, "#{File.basename(html_file, ".htm")}.html")
end
Dir.glob("*.htm").each do |html_file|
FileUtils.mv html_file, "#{html_file.sub(/.htm/,'.html')}"
end
Here's how I did it though it did not use a FileUtils method and I skipped ahead and did string manipulation before it was discussed in the lessons.
Dir.glob("*.htm") {|old_filename| #Save file names w/ .htm to old_
tmp_filename = old_filename.slice(0..-5) #Remove (.htm) the file extension
new_filename = tmp_filename + '.html' #Append the .html extension
puts new_filename #Display renamed file names
}
I want to create a temporary .zip in rails. For creating zip file I am using rubyzip gem.
Currently I am doing this:
zfname = Tempfile.new(['somename','.zip'], Rails.root.to_s + '/tmp/')
Zip::ZipFile.open(zfname.path, Zip::ZipFile::CREATE) do |zipfile|
zipfile.add(file, basepath + file)
end
This generates following error:
Zip::ZipError: Zip end of central directory signature not found
Is it possible to use Tempfile for zip? If yes, what is wrong here?
In my rails app when I needed to send zip files to user, I just stored them in a buffer and used 'send data' method in controller.
I was trying to use 'Tempfile' initially but it had an added task of removing zip files after sending it to user which is a pain.
Is this something you are looking for?
Zip::OutputStream.write_buffer do |stream|
file_paths.each_with_index do |file_path, index|
# rename the pdf
stream.put_next_entry("#{name}-#{index + 1}.pdf")
# add pdf to zip
stream.write IO.read(file_path)
end
end
So it doesn't actually look like you need or want a Tempfile. You really want a random path in the Rails.root/tmp directory. Try something like this:
zfpath = Rails.root.join('tmp', "somename-#{SecureRandom.hex(8)}.zip"
Zip::ZipFile.open(zfpath, Zip::ZipFile::CREATE) do |zipfile|
zipfile.add(file, basepath + file)
end
Update:
While it's far more complex, you can find a discussion of how to do this with a Tempfile here - http://thinkingeek.com/2013/11/15/create-temporary-zip-file-send-response-rails/ .
I have numerous files in a directory app/assets/downloadables/ and I want authenticated users to be able to download arbitrary files by name in params within that directory or any subdirectories.
How can I sanitise the input to send_file to prevent users from accessing arbitrary files on the server?
At the moment I'm looking at doing something like this, but I'm not confident that it's safe:
DOWNLOADS_ROOT = File.join(Rails.root, "app", "assets", "downloadables")
# e.g. request.path = "/downloads/subdir/file1.pdf"
file = request.path.gsub(/^\/downloads\//,'').gsub('..','').split('/')
# send file /app/assets/downloadables/subdir/file1.pdf
send_file File.join(DOWNLOADS_ROOT, file)
Would this sufficiently protect against app-wide arbitrary file access or are there improvements or a different approach that would be better?
I found an answer to this here: http://makandracards.com/makandra/1083-sanitize-user-generated-filenames-and-only-send-files-inside-a-given-directory
This file needed to be created per the link:
app/controllers/shared/send_file_inside_trait.rb
module ApplicationController::SendFileInsideTrait
as_trait do
private
def send_file_inside(allowed_path, filename, options = {})
path = File.expand_path(File.join(allowed_path, filename))
if path.match Regexp.new('^' + Regexp.escape(allowed_path))
send_file path, options
else
raise 'Disallowed file requested'
end
end
end
end
To be used as follows in controllers:
send_file_inside File.join(Rails.root, 'app', 'assets', 'downloadables'), request.path.gsub(/^\/downloads\//,'').split('/')
The magic happens where the calculated path of allowed_path + file_name is entered into expand_path which will strip out any special directory browsing strings and just return an absolute path. That resolved path is then compared against the allowed_path to ensure that the file being requested resides within the allowed path and/or sub-directories.
Note that this solution requires the Modularity gem v2 https://github.com/makandra/modularity
I'm using the following code to try and get all files from ftp using Ruby.
files = ftp.list()
files.each do |file|
ftp.gettextfile(file)
end
The problem is ftp.list returns a whole line of information, not just the filename e.g.
-rw-r--r-- 1 ftp ftp 0 May 31 11:18 brett.txt
How do I extract the filname from this string?
Many thanks
You can use the nlst public method like this
files = ftp.nlst("*.zip")|ftp.nlst("*.txt")|ftp.nlst("*.xml")
#optionally exclude falsely matched files
exclude = /\.old|temp/
#exclude files with 'old' or 'temp' in the name
files = files.reject{ |e| exclude.match e } #remove files matching the exclude regex
files.each do |file|
#do something with each file here
end
If you want to process the output of ftp.list you may find net-ftp-list useful.
However, list appears to be useful, as you can pass in a matching pattern, which it doesn't appear that nlst supports. I just did a quick-and-dirty hack to make list output work:
ftp.list("*.zip") do |zipfile|
zipfile = zipfile.split(/\s+/).last
# ... do something with the file
end