Ruby recurse directory - ruby-on-rails

I am trying to recurse a directory, and all its subdirectories. I dont want to use "Find" or any other way except this one:
task :locate do
Dir.chdir(Dir.pwd+"/public/servers_info/config/deploy/")
puts "Current Directory is: "+ Dir.pwd
dir = Dir.pwd
def get_information(dir)
Dir.foreach(".") {|f|
next if f == '.' or f == '..'
if File.directory? f
puts f
#puts Dir.pwd+"/"+f
get_information(Dir.pwd+"/"+f)
else
puts "Not Directory"
end
}
end
get_information(dir)
end
I am pretty sure that it will work, I just dont know why it get stucks in the first directory! It enters the base directory, checks is the file is a directory or not, and then runs the SAME function again. But it doesnt! it gets stuck on the first folder and I get an error! Any help?

Your code is always looking at the "current" (.) directory. Your get_information method passes in a value bound to dir, which you never use.
Since you never use that parameter, you never change directories.
What you're trying to do is easier with Dir.glob, but if you're wedded to your solution, you'll need to change Dir.foreach(".") to something like Dir.foreach(dir).
Edited to add: If all you want is to print out a list of subdirectories, I would do
puts Dir.glob('*/**').select { |f| File.directory? f}
This includes only directories. If you want pretty close to the exact output of your existing code, I would do something like:
puts Dir.glob('*/**').map { |f| File.directory?(f)? f : "Not a Directory" }

Check out Dir.glob. Docs here

Related

Write a script in Ruby to rename all *.htm files to *.html

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
}

create file in different directories with ruby

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

Load Lua-files by relative path

If I have a file structure like this:
./main.lua
./mylib/mylib.lua
./mylib/mylib-utils.lua
./mylib/mylib-helpers.lua
./mylib/mylib-other-stuff.lua
From main.lua the file mylib.lua can be loaded with full path require('mylib.mylib'). But inside mylib.lua I would also like to load other necessary modules and I don't feel like always specifying the full path (e.g. mylib.mylib-utils). If I ever decide to move the folder I'm going to have a lot of search and replace. Is there a way to use just the relative part of the path?
UPD. I'm using Lua with Corona SDK, if that matters.
There is a way of deducing the "local path" of a file (more concretely, the string that was used to load the file).
If you are requiring a file inside lib.foo.bar, you might be doing something like this:
require 'lib.foo.bar'
Then you can get the path to the file as the first element (and only) ... variable, when you are outside all functions. In other words:
-- lib/foo/bar.lua
local pathOfThisFile = ... -- pathOfThisFile is now 'lib.foo.bar'
Now, to get the "folder" you need to remove the filename. Simplest way is using match:
local folderOfThisFile = (...):match("(.-)[^%.]+$") -- returns 'lib.foo.'
And there you have it. Now you can prepend that string to other file names and use that to require:
require(folderOfThisFile .. 'baz') -- require('lib.foo.baz')
require(folderOfThisFile .. 'bazinga') -- require('lib.foo.bazinga')
If you move bar.lua around, folderOfThisFile will get automatically updated.
You can do
package.path = './mylib/?.lua;' .. package.path
Or
local oldreq = require
local require = function(s) return oldreq('mylib.' .. s) end
Then
-- do all the requires
require('mylib-utils')
require('mylib-helpers')
require('mylib-other-stuff')
-- and optionally restore the old require, if you did it the second way
require = oldreq
I'm using the following snippet. It should work both for files loaded with require, and for files called via the command line. Then use requireRel instead of require for those you wish to be loaded with a relative path.
local requireRel
if arg and arg[0] then
package.path = arg[0]:match("(.-)[^\\/]+$") .. "?.lua;" .. package.path
requireRel = require
elseif ... then
local d = (...):match("(.-)[^%.]+$")
function requireRel(module) return require(d .. module) end
end
Under the Conky's Lua environment I've managed to include my common.lua (in the same directory) as require(".common"). Note the leading dot . character.
Try this:Here is my findings:
module1= require(".\\moduleName")
module2= dofile("..\\moduleName2.lua")
module3 =loadfile("..\\module3.lua")
To load from current directory. Append a double backslash with a prefix of a fullstop.
To specify a directory above use a prefix of two fullstops and repeat this pattern for any such directory.e.g
module4=require("..\\..\\module4")

Rails detect changes to files programatically

I would like to write a method that programatically detects whether any of the files in my rails app have been changed. Is it possible do do something like an MD5 of the whole app and store that in a session variable?
This is mostly for having some fun with cache manifest. I already have a dynamically generated cache and it works well in production. But in my dev environment, I would like the id of that cache to update whenever I change anything in the app directory (as opposed to every 10 seconds, which is how I have it setup right now).
Update
File.ctime(".") would be perfect, except that "." is not marked as having changed when deeper directory files have changed.
Does it make sense to iterate through all directories in "." and add together the ctimes for each?
Have you considered using Guard.
You can programatically do anything whenever a file in your project changes.
There is a nice railscast about it
There is a simple ruby gem called filewatcher. This is the most advanced example:
require 'filewatcher'
FileWatcher.new(["README.rdoc"]).watch() do |filename, event|
if(event == :changed)
puts "File updated: " + filename
end
if(event == :delete)
puts "File deleted: " + filename
end
if(event == :new)
puts "New file: " + filename
end
end
File.ctime is the key. Iterate through all files and create a unique id based on the sum of all their ctimes:
cache_id = 0
Dir.glob('./**/*') do |this_file|
ignore_files = ['.', '..', "log"]
ignore_files.each do |ig|
next if this_file == ig
end
cache_id += File.ctime(this_file).to_i if File.directory?(this_file)
end
Works like a charm, page only re-caches when it needs to, even in development.

Ruby Net::FTP, extract filename from ftp.list()

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

Resources