How to match multiple patterns with Dir.glob? - ruby-on-rails

In my Rails app I am trying to collect the paths to all the files contained in two different directories using Dir.glob.
The following code works but is not very concise. Isn't there a way two match two patterns at once with Dir.glob?
common_file_paths = Dir.glob("app/assets/mystuff/*").reject do |path|
File.directory?(path)
end
more_file_paths = Dir.glob("app/assets/mystuff/more/*").reject do |path|
File.directory?(path)
end
file_paths = common_file_paths + more_file_paths

Dir.glob also accepts an array of patterns.
Dir.glob(["app/assets/mystuff/*", "app/assets/mystuff/more/*"])

this should do it for you .. tested it in my local machine and it works as expected.
lets say , you have the following directory and subdirectory :
z$ find deletpractic/
deletpractic/
deletpractic/sub_dir
deletpractic/sub_dir/file1_in_subdir.txt
deletpractic/sub_dir/file2_in_subdir.txt
deletpractic/text1
deletpractic/text2
deletpractic/text3
deletpractic/text4
deletpractic/text5
deletpractic/text6
deletpractic/text7
it pretty much boils down to this Dir.glob("/mydir/**/*")
[za]$ /usr/bin/ruby -rpp -e 'common_file_paths = Dir.glob("/dev/deletpractic/**/*").reject do |path| File.directory?(path) end ; pp common_file_paths'
Output :
["/dev/deletpractic/sub_dir/file1_in_subdir.txt",
"/dev/deletpractic/sub_dir/file2_in_subdir.txt",
"/dev/deletpractic/text1",
"/dev/deletpractic/text2",
"/dev/deletpractic/text3",
"/dev/deletpractic/text4",
"/dev/deletpractic/text5",
"/dev/deletpractic/text6",
"/dev/deletpractic/text7"]

Related

string.gsub() on two paths not working

I looped in the directory tree of a "content" folder containing subdirectories and markdown files. Then I need to know the relative path of those markdowns from that "content" folder.
In bash script I would do something like that :
CONTENT_PATH="/home/myusr/apps/myapp/content"
file_path="/home/myusr/apps/myapp/content/file/pgp.md"
echo "${file_path#$CONTENT_PATH}"
# /file/pgp.md
So in Lua I didn't found something like that, so I've tried with string.gsub():
print(string.gsub(file_path, CONTENT_PATH, ""))
-- /home/myusr/apps/myapp/content/file/pgp.md 0
But it's not working, it seems my CONTENT_PATH string does not match and I don't know why?
print(CONTENT_PATH)
-- /home/hs0ucy/_01_http/fakestache-lua/content
print(file_path)
-- /home/hs0ucy/_01_http/fakestache-lua/content/file/pgp.md
Thanks!
PS : I'm new to Lua.
From: Lua string.gsub with a hyphen
The hyphen is a special character in Lua, and needs to be escaped like so: %-.
I discovered this by slowly making CONTENT_PATH longer and longer until it was no longer working. Good ol' binary search!
EDIT: if you can't modify your CONTENT_PATH but you're sure that file_path has CONTENT_PATH in it:
contentPathLen = string.len(CONTENT_PATH)
print(string.sub(file_path, contentPathLen + 1))
-- Output: /file/pgp.md
Or if you need to verify that file_path starts with CONTENT_PATH:
base = string.sub(file_path, 0, contentPathLen)
if base == CONTENT_PATH then
print("file_path is under CONTENT_PATH")
end

regexp matching in rails app

I have the following string that needs to be replaced by an empty character in rails. Followed many tutorials and docs. Please help me achieve this.
String:
/home/<someword>/dbdumps/backup.sql
To be replaced as:
backup
To get the file name from a path, I'd use File#basename
File.basename('/home/<someword>/dbdumps/backup.sql', '.sql')
#=> 'backup'
if "someword" is the only thing that changes you dont even need regex.
Assume
path = "/home/<someword>/dbdumps/backup.sql"
then
path.split("/").last.split(".").first
returns
=> "backup"
The easiest solution would be a gsub (string substitution) like so:
string = "home/<someword>/dbdumps/backup.sql"
new_string = string.gsub(%r{home/(.*)/dbdumps/backup.sql}, 'backup' )
This is a simple example of string substitution.
In a rails app i do a Net:SSH:start( ) and run ssh.exec!('ls /home//dbdumps/.sql'). I am ?sending the output to a string and then i have to display the list of the files. For that I am taking the output into a string and trying to do a gsub. Is this the right approach?
I would not consider it pretty (naive code, no error checking, loops with requests) but something like this could do the job for you. It depends if you want to end up with just the backup names or the full path.
ssh.exec!("ls -l /home/") do |channel, stream, data|
directories << data if stream == :stdout
end
directories.each do |dir|
ssh.exec!("ls -l /home/" + dir + "dbdumps") do |channel, stream, data|
backup_names << /home/" + dir + "/" + data if stream == :stdout
end
end
hope this helps

Ruby recurse directory

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

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

Reading the first line of a file in Ruby

I want to read only the first line of a file using Ruby in the fastest, simplest, most idiomatic way possible. What's the best approach?
(Specifically: I want to read the git commit UUID out of the REVISION file in my latest Capistrano-deployed Rails directory, and then output that to my tag. This will let me see at an http-glance what version is deployed to my server. If there's an entirely different & better way to do this, please let me know.)
This will read exactly one line and ensure that the file is properly closed immediately after.
strVar = File.open('somefile.txt') {|f| f.readline}
# or, in Ruby 1.8.7 and above: #
strVar = File.open('somefile.txt', &:readline)
puts strVar
Here's a concise idiomatic way to do it that properly opens the file for reading and closes it afterwards.
File.open('path.txt', &:gets)
If you want an empty file to cause an exception use this instead.
File.open('path.txt', &:readline)
Also, here's a quick & dirty implementation of head that would work for your purposes and in many other instances where you want to read a few more lines.
# Reads a set number of lines from the top.
# Usage: File.head('path.txt')
class File
def self.head(path, n = 1)
open(path) do |f|
lines = []
n.times do
line = f.gets || break
lines << line
end
lines
end
end
end
You can try this:
File.foreach('path_to_file').first
How to read the first line in a ruby file:
commit_hash = File.open("filename.txt").first
Alternatively you could just do a git-log from inside your application:
commit_hash = `git log -1 --pretty=format:"%H"`
The %H tells the format to print the full commit hash. There are also modules which allow you to access your local git repo from inside a Rails app in a more ruby-ish manner although I have never used them.
first_line = open("filename").gets
I think the jkupferman suggestion of investigating the git --pretty options makes the most sense, however yet another approach would be the head command e.g.
ruby -e 'puts `head -n 1 filename`' #(backtick before `head` and after `filename`)
Improving on the answer posted by #Chuck, I think it might be worthwhile to point out that if the file you are reading is empty, an EOFError exception will be thrown. Catch and ignore the exception:
def readit(filename)
text = ""
begin
text = File.open(filename, &:readline)
rescue EOFError
end
text
end
first_line = File.readlines('file_path').first.chomp

Resources