Find and delete oldest AVI file recursively - ruby

I've been trying to write a Ruby script to find and delete the oldest AVI file in a folder. I found a script in Python that is very close, and I got a good start on the Ruby solution myself with:
require 'fileutils'
stat = Sys::Filesystem.stat("/")
mb_available = stat.block_size * stat.blocks_available / 1024 / 1024
#if there is less than 130MB free
if mb_available < 130000
require 'find'
movie_file_paths = []
#grab all the files in the folder
Find.find('/Users/jody/Movies') do |path|
movie_file_paths << path if /.*\.avi/.match(path) != nil
end
end
But, I'm having a tough time with the rest. Any help would be appreciated!
EDIT:
This was the solution:
movie_file_paths = []
Dir.glob("/Users/jody/Movies/**/*.avi").each { |file| movie_file_paths << file if File.file? file }
movie_file_paths.sort_by {|f| File.mtime(f)}
deleteme = movie_file_paths.first

I see you've already selected an answer but it can be a one-liner:
File.delete(Dir.glob("/Users/jody/Movies/**/*.avi").sort_by{|f| File.mtime(f)}.first)
Update: I came across this a few years later and thought to myself, "I can make that shorter!"
File.delete(Dir["/Users/jody/Movies/**/*.avi"]).min_by{|f| File.mtime(f)})

File has the methods you want, specifically ctime for "last changed" times (creation times on NTFS), mtime if you want "last modified" times, or atime for "last accessed" times. Combining this with Dir::glob, you can easily get a list of files sorted by datetime:
videos = Dir['/Users/jody/Movies/*.avi'].sort_by(&:ctime)
Deleting the last one is very simple:
File.delete videos.last

Use File.mtime(filename) to get the last modified time of the file.
movie_file_path.sort_by {|f| File.mtime(f)} will return a sorted array by mtime. You can then delete the file using File.delete(filename).
Edit: Last accessed time atime might be a better option than mtime.

Related

How do I get the entirety of an uncompressed gzip file using Zlib?

I am trying to uncompress a 823,000 line file, but I'm only receiving 26,000 lines of the file. I'm new to I/O and for some reason, not grasping why this is the case. Here is my code:
Zlib::GzipReader.open( file_path ) do |gz|
puts gz.readlines.count
end
Any direction would be appreciated.
Thanks in advance.
Ok, so I managed to fix this.
It turns out the server log file I was using had about 29 streams of data in it. Zlib::GzipReader only read the first one. In order to fix it, I had to loop through until all 29 streams had been read:
File.open( file_path ) do |file|
zio = file
loop do
io = Zlib::GzipReader.new( zio )
uncompressed += io.read
unused = io.unused # where I'm writing my file
break if unused.nil?
zio.pos -= unused.length
end
end

Ruby Simple Read/Write File (Copy File)

I am practicing Ruby, and I am trying to copy contents from file "from" to file "to". can you tell me where I did it wrong?
thanks !
from = "1.txt"
to = "2.txt"
data = open(from).read
out = open(to, 'w')
out.write(data)
out.close
data.close
Maybe I am missing the point, but I think writing it like so is more 'ruby'
from = "1.txt"
to = "2.txt"
contents = File.open(from, 'r').read
File.open(to, 'w').write(contents)
Personally, however, I like to use the Operating systems terminal to do File operations like so. Here is an example on linux.
from = "1.txt"
to = "2.txt"
system("cp #{from} #{to}")
And for Windows I believe you would use..
from = "1.txt"
to = "2.txt"
system("copy #{from} #{to}")
Finally, if you were needing the output of the command for some sort of logging or other reason, I would use backticks.
#A nice one liner
`cp 1.txt 2.txt`
Here is the system and backtick methods documentation.
http://ruby-doc.org/core-1.9.3/Kernel.html
You can't perform data.close — data.class would show you that you have a String, and .close is not a valid String method. By opening from the way you chose to, you lost the File reference after using it with your read. One way to fix that would be:
from = "1.txt"
to = "2.txt"
infile = open(from) # Retain the File reference
data = infile.read # Use it to do the read
out = open(to, 'w')
out.write(data)
out.close
infile.close # And finally, close it

How to detect a file rename using Rugged?

I'm a novice Rugged user, and I'm attempting to detect file renames in the commit history. I'm diffing each commit against its first parent, as follows:
repo = Rugged::Repository.discover("foo")
walker = Rugged::Walker.new(repo)
walker.sorting(Rugged::SORT_TOPO)
walker.push("master")
walker.each.take(200).each do |commit|
puts commit.oid
puts commit.message
diffs = nil
# Handle Root commit
if commit.parents.count > 0 then
diffs = commit.parents[0].diff(commit)
else
diffs = commit.diff(nil)
end
(files,additions,deletions) = diffs.stat
puts "Files changed: #{files}, Additions: #{additions}, Deletions: #{deletions}"
paths = [];
diffs.each_delta do |delta|
old_file_path = delta.old_file[:path]
new_file_path = delta.new_file[:path]
puts delta.status
puts delta.renamed?
puts delta.similarity
paths += [delta]
end
puts "Paths:"
puts paths
puts "===================================="
end
walker.reset
However, when I do have a rename, the program will output an addition and a removal (A and D status). This matches the output of git log --name-status.
On the other hand, I found out that using git log --name-status --format='%H' --follow -- b.txt correctly shows the rename as R100.
The repo history and the outputs of git can be seen in the following gist: https://gist.github.com/ifigueroap/60716bbf4aa2f205b9c9
My question is how to use the Diff, or Delta objects of Rugged to detect such a file rename...
Thanks
Before accessing diffs.stat, you should call diffs.find_similar! with :renames => true. That'll modify the diffs object to do include rename information. This is not done by default, as the underlying operation is quite complex and not needed in most cases.
Check the documentation for find_similar! here: https://github.com/libgit2/rugged/blob/e96d26174b2bf763e9dd5dd2370e79f5e29077c9/ext/rugged/rugged_diff.c#L310-L366 for more options.

Selenium Webdriver using Ruby: write text to file

I would like to write text to a file multiple times (appending).
Currently I am using: In this scenario I captured the system time in endtime and starttime.
File.open("c:\\temp\\myfile.txt", "w").write("My first input: #{endtime-starttime} seconds \n")
I would like to continue this multiple times in various places in my script but it does not seem to be working correctly. The text file seems to be writing over itself. Is there a way in a script to write text in different rows?
Thanks,
Scott
Here's a better example
#------------------------------------------------------------------------------------------------ ---------------------
#Log into System
#---------------------------------------------------------------------------------------------------------------------
starttime=Time.new
LoginButton = driver.find_element(:xpath, "/html/body/div[3]/div/div[2]/ul/li[3]/a")
LoginButton.click
option = driver.find_element(:xpath, "/html/body/div/div[1]/div/div[3]/div[1]/form/div[3]/ul/li[1]/input")
option.send_keys"blah"
option = driver.find_element(:id, "password")
option.send_keys"blah"
option = driver.find_element(:xpath, "/html/body/div/div[1]/div/div[3]/div[1]/form/div[3]/ul/li[3]/input")
option.click
endtime=Time.new
puts"Login: #{endtime-starttime} seconds"
File.open("c:\\temp\\myfile.txt", "w").write("Login: #{endtime-starttime} seconds \n")
puts"Login Done"
#---------------------------------------------------------------------------------------------------------------------
#Performance Test Course
#---------------------------------------------------------------------------------------------------------------------
starttime=Time.new
driver.switch_to.frame "contentFrame" #Sets focus on the "UR Courses Online Module"
option = driver.find_element(:link_text, "Performance Test Course")
option.click
endtime=Time.new
puts"Performance Test Course Link: #{endtime-starttime} seconds"
File.open("c:\\temp\\myfile.txt", "w").write("Performance Test Course Link: #{endtime-starttime} seconds \n")
puts"Performance Test Course Done"
You probably want to store the open file object in a variable so that when you write a new line to your file it is written to the end. Your previous code would open the given file write the line at position 0 in the file then close the file.
file = File.open("text.txt", "w")
file.write "hello world"
Or you can use the "a" flag which opens a file for write at the end of the file.
File.open("c:\\temp\\myfile.txt", "a+").write("My first input: #{endtime-starttime} seconds \n")
You are using w which truncates the file before writing to it.
Use:
File.open("c:\\temp\\myfile.txt", "a+").write("My first input: #{endtime-starttime} seconds \n")

Zlib inflate error

I am trying to save compressed strings to a file and load them later for use in the game. I kept getting "in 'finish': buffer error" errors when loading the data back up for use. I came up with this:
require "zlib"
def deflate(string)
zipper = Zlib::Deflate.new
data = zipper.deflate(string, Zlib::FINISH)
end
def inflate(string)
zstream = Zlib::Inflate.new
buf = zstream.inflate(string)
zstream.finish
zstream.close
buf
end
setting = ["nothing","nada","nope"]
taggedskills = ["nothing","nada","nope","nuhuh"]
File.open('testzip.txt','wb') do |w|
w.write(deflate("hello world")+"\n")
w.write(deflate("goodbye world")+"\n")
w.write(deflate("etc")+"\n")
w.write(deflate("etc")+"\n")
w.write(deflate("Setting: name "+setting[0]+" set"+(setting[1].class == String ? "str" : "num")+" "+setting[1].to_s)+"\n")
w.write(deflate("Taggedskill: "+taggedskills[0]+" "+taggedskills[1]+" "+taggedskills[2]+" "+taggedskills[3])+"\n")
w.write(deflate("etc")+"\n")
end
File.open('testzip.txt','rb') do |file|
file.each do |line|
p inflate(line)
end
end
It was throwing errors at the "Taggedskill:" point. I don't know what it is, but trying to change it to "Skilltag:", "Skillt:", etc. continues to throw a buffer error, while things like "Setting:" or "Thing:" work fine, while changing the setting line to "Taggedskill:" continues to work fine. What is going on here?
In testzip.txt, you are storing newline separated binary blobs. However, binary blobs may contain newlines by themselves, so when you open testzip.txt and split it by line, you may end up splitting one binary blob that inflate would understand, into two binary blobs that it does not understand.
Try to run wc -l testzip.txt after you get the error. You'll see the file contains one more line, than the number of lines you are putting in.
What you need to do, is compress the whole file at once, not line by line.

Resources