Mixing Ruby and bash commands -- mv returns "x and y are the same file" - ruby-on-rails

So I have a Ruby script (using Ruby because we have a library of pre-existing code that I need to use). From within Ruby I am using backticks to call Linux commands, specifically in this case the "mv" command. I am trying to move one file to another location but I keep getting the error message that x and y are "the same file" even though they are very clearly NOT the same file.
Here is the code in Ruby:
#!/usr/local/rvm/rubies/ruby-2.1.1/bin/ruby
masterFiles=[]
masterFiles << "/mnt/datadrive/Data Capture/QualityControl/UH_HRA_SVY/Scans and DataOutput/Data/UH_HRA_SVY_DATA.txt"
masterFiles << "/mnt/datadrive/Data Capture/QualityControl/UH_HRA_SVY_SPAN/Scans and DataOutput/Data/UH_HRA_SVY_SPAN_DATA.txt"
tm=Time.new.strftime("%Y%m%d")
masterFiles.each do |mf|
if File.exist?(mf)
qmf=39.chr + mf + 39.chr
`cat #{qmf} >> /tmp/QM`
savename=39.chr + \
"/mnt/datadrive/Data Capture/QualityControl/UH_HRA_SVY/Scans and DataOutput/Data/DailyFiles/" + \
File.basename(mf).gsub(".txt","_"+tm) + ".txt" + 39.chr
`mv #{qmf} #{savename}`
end
end
The error that I get is this:
mv: `/mnt/datadrive/Data Capture/QualityControl/UH_HRA_SVY_SPAN/Scans
and DataOutput/Data/UH_HRA_SVY_SPAN_DATA.txt' and `/mnt/datadrive/Data
Capture/QualityControl/UH_HRA_SVY/Scans and
DataOutput/Data/DailyFiles/UH_HRA_SVY_SPAN_DATA_20140530.txt' are the
same file
If I change this line:
`mv #{qmf} #{savename}`
To this:
puts "mv #{qmf} #{savename}"
And then run the output, it works as expected.
I am pretty sure that this has to do with spaces in the path. I have tried every combination of double-quoting, triple-quoting, quadruple-quoting, and back-slashing I can think of to resolve this but no go. I have also tried using FileUtils.mv but get what is basically the same error worded differently.
Can anybody help ? Thanks a lot.
p.s. I realize it's entirely possible that I could be going about this in an entirely wrong-headed way, so feel free to point that out if so. However, I am trying to use the tools which I already have some knowledge of (cat, mv, etc) instead of re-inventing the wheel.

You could use FileUtils.mv
I often do aliases like so:
require 'fileutils'
def mv(from, to)
FileUtils.mv(from, to)
end
And inside the mv() method I do additional safeguards, i.e. if the file does not exist, if there is a lack of permissions and so forth.
If you then still have problems with filenames that have ' ' blank characters, try to put the file into a "" quote like:
your_target_location = "foo/bar bla"

Related

Need to collect only emails using Ruby code

I've received a list of emails that I'd like to run an email campaign on, however, in the list there are some URL's... and it complicates things.
Here's the standard formatting of the email address, for example:
news#ydr.com
I'd like to paste the list in terminal and run a command to ONLY capture all of the email addresses and save them to a file and remove any URLS.
Please advise! It is much appreciated :)
If you are just looking to catch most emails this regex might work.
I got this regex from here How to validate an email address using a regular expression?
They talk about the much more complicated RFC822 email regex
#!/usr/bin/env ruby
input = $stdin.readlines # ctrl + D after paste
input.each do |f|
puts f if f[/^[a-zA-Z0-9_.+\-]+#[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$/]
end
# test input
# foo#bar.com
# www.cnn.com
# test.email#go.com
# turdburgler#mcdo.net
# http://www.google.com
To write emails to a file:
#!/usr/bin/env ruby
file = File.open("emails.txt", "w")
input = $stdin.readlines # ctrl + D after paste
input.each do |f|
file.write(f) if f[/^[a-zA-Z0-9_.+\-]+#[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$/]
end
file.close
Just to be clear, this is a ruby script which should be ran like this.
Save the script as a file, ie email_parser.rb.
chmod +x email_parser.rb
./email_parser.rb # this will wait for stdin, here you paste the list in to the terminal
When the terminal is hanging waiting, paste the list of emails in, then press ctrl + D to tell the program that this is the EOF. The program will then run through the list of emails/urls and parse. The output of this will be a file if using the updated script. The file will be in the same folder you ran the script and be called emails.txt

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

Modifying Brightness/Contrast of Image with RMagick

I'm trying to write a script to take a PDF and increase the brightness/contrast such that my scanned handwritting is actually readable. I am able to do this with Photoshop (which is really tedious), but I can't figure out what RMagick methods to use to produce a similar result.
Any pointers? Thanks for the help.
I ended up using Fred's ImageMagick scripts to make the handwriting readable see : http://www.fmwconcepts.com/imagemagick/
I ended up not using RMagick for this part; instead I just called imagemagick's convert terminal command from ruby. It is a little bit convoluted - but it worked for me. Some sample code is below:
localthres_script = '~/Downloads/test/localthresh.sh' # CONSTANT LOCATION
params = '-m 3 -r 25 -b 20 -n yes'
pdf = Magick::ImageList.new("#{dir}/#{pdf_name_wo_ext}.pdf")
i=1
pdf.each do |page|
image_name = "#{pdf_name_wo_ext}_#{i}"
puts "==> Enhancing images..."
%x[#{localthres_script} #{params} #{dir}/#{image_name}.png #{dir}/PDF_SCRIPT/enhanced/#{image_name}.png]
puts "==> Moving images..."
%x[mv #{dir}/#{image_name}.png #{dir}/PDF_SCRIPT/original/#{image_name}.png]
i = i+1
end # each
I know this isn't the cleanest code, but it worked for me.

How do I make sure that a directory name is quoted in OMake?

I have a relatively complicated suite of OMake files designed for cross-compiling on a specific platform. My source is in C++.
I'm building from Windows and I need to pass to the compiler include directories which have spaces in their names. The way that the includes string which is inserted in the command line to compile files is created is by the line:
public.PREFIXED_INCLUDES = $`(addprefix $(INCLUDES_OPT), $(set $(absname $(INCLUDES))))
At some other point in the OMake files I have a line like:
INCLUDES += $(dir "$(LIBRARY_LOCATION)/Path with spaces/include")
In the middle of the command line this expands to:
-IC:\Library location with spaces\Path with spaces\include
I want it to expand to:
-I"C:\Library location with spaces\Path with spaces\include"
I don't want to change anything but the "INCLUDES += ..." line if possible, although modifying something else in that file is also fine. I don't want to have to do something like change the definition of PREFIXED_INCLUDES, as that's in a suite of OMake files which are part of an SDK which may change beneath me. Is this possible? If so, how can I do it? If not, in what ways can I make sure that includes with spaces in them are quoted by modifying little makefile code (hopefully one line)?
The standard library function quote adds escaped quotes around its argument, so it should do the job:
INCLUDES += $(quote $(dir "$(LIBRARY_LOCATION)/Path with spaces/include"))
If needed, see quote in Omake manual.
In case someone else is having the same problem, I thought I'd share the solution I eventually went with, having never figured out how to surround with quotes. Instead of putting quotes around a name with spaces in it I ended up converting the path to the short (8.3) version. I did this via a a simple JScript file called shorten.js and a one line OMake function.
The script:
// Get Access to the file system.
var FileSystemObject = WScript.CreateObject("Scripting.FileSystemObject");
// Get the short path.
var shortPath = FileSystemObject.GetFolder(WScript.Arguments(0)).ShortPath;
// Output short path.
WScript.StdOut.Write(shortPath);
The function:
ShortDirectoryPath(longPath) =
return $(dir $(shell cscript /Nologo $(dir ./tools/shorten.js) "$(absname $(longPath))"))
So now I just use a line like the following for includes:
INCLUDES += $(ShortDirectoryPath $(dir "$(LIBRARY_LOCATION)/Path with spaces/include"))

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