Errors with getting file permissions with File.Stat (Errno::ENOENT) - ruby

I'm new to programming and I am trying to figure out how to grab all the recursive directories of my array, and get the file permissions of all of them.
Googling was pointing me to file.stat, however the code is stating there is no such file or directory called 'stat'. For context, after getting the file permissions, my next objective is to be able to compare the permissions of the file owner to the group to determine any differences. I think part of my problem displayed with 'File::Stat:0x7f2407a9e908' is that it's not converting to an integer.
Any suggestions on reading material or revision would be greatly appreciated.
Here is my code so far:
%w(/etc /bin /usr/bin /usr/lbin /usr/usb /sbin /usr/sbin).each do |dir|
Dir.glob("#{dir}/**").each do |c|
s = File.stat("#{c}")
puts s
end
end
And here is my return:
#<File::Stat:0x7f2407a9e908>
test.rb:3:in `stat': No such file or directory - /usr/bin/chef-zero (Errno::ENOENT)
from test.rb:3
from test.rb:2:in `each'
from test.rb:2
from test.rb:1:in `each'
from test.rb:1

Related

How to use `Dir` to reference directories outside the working directory

The closest issue I could find on Stack Overflow was "Path outside of project, Ruby Dir", but the user appears to have been in the wrong development environment.
My issue is that the Dir class only gives information relative to the working directory. For instance, if I'm in C:/Users/john/Developer and this directory only has two subdirectories A and B then
$ ruby -e "p Dir['*']"
will return ["A", "B"]. This seems intended, but what if there is a directory C:/Users/jane/Developer/C that I need to run a command in using a script in C:/Users/john/Developer?
Running
Dir.chdir('C:/Users/jane/Developer/C') { %x[lerna clean] }
returns the error:
-e:1:in `chdir': No such file or directory # dir_s_chdir - C:/Users/jane/Developer/C (Errno::ENOENT)
from -e:1:in `<main>'
Is there a way to access directories outside of the working directory using the Dir class? It seems absurd to have to require scripts to be written at a root level.
Note, using %x[] to run the command in C:/Users/jane/Developer/C also doesn't seem to work.

Ruby: File not found exception, even though it exists, and is passed down by loop

I'm practicing Ruby after growing to resent Java with a simple little program that determines how similar a few thousand documents are. I did the same thing in Java junior year of high school for a data structures project, and actually wrote the fastest program the teacher had ever seen (apparently), but somehow I can't transfer that over to Ruby.
I'm trying to create an array of files:
array = Dir.foreach("/home/rj/Documents/Ruby Code/Catching Plaigarists/Large number of documents") do |filename|
File.new(filename, "r") unless filename.start_with?(".") #Prevents it from returning current and parent directories
end
When I run it in the terminal, I get this rather irritating exception:
/home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:2:in `initialize': No such file or directory # rb_sysopen - bmu390.shtml.txt (Errno::ENOENT)
from /home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:2:in `new'
from /home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:2:in `block in <main>'
from /home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:1:in `foreach'
from /home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:1:in `<main>'
I checked to make sure the document existed. It did. Ran it again a few more times. Same thing with the same document. Naturally, I tried deleting the document. But then it did the same thing for some other document. And when I deleted that document, it managed to find some problem with some other document with a higher alphabetical precedence that it seemed to do just fine with the first two times around.
Why can't it find these documents, and if they don't exist, why does the loop pass the filenames down in the first place? What am I doing wrong? Why me?
(Also I'm running Fedora with Cinnamon, if that would have any impact.)
Your working directory is different than the directory your looping through. You could store the path your working with as a string and then concatenate it to the filename you get back from your loop.
path = "/home/rj/Documents/Ruby Code/Catching Plaigarists/Large number of documents/"
array = Dir.foreach(path) do |filename|
File.new((path + filename), "r") unless filename.start_with?(".")
end
You'll need the slash at the end of the path variable to build the correct path.

How can I copy files and rename them according to their origin directories using Ruby?

I have many directories with generically named txt files inside. I want to make copies of the txt files, rename them according to the containing directory of each, then move them to the parent directory (that being the directory that holds the directories that hold the original txt files, designated "txts" in the script below). I want to retain the original txt files with their original names in their original directories as well so that nothing within the original directories changes.
I have an old script that I think achieved (some of) my goals once, perhaps moving instead of copying the original txt files, but I'm unable to run it successfully now:
require 'find'
require 'fileutils'
Find.find("txts") do |path|
if FileTest.directory?(path)
next
end
ret = path.scan(/.*txts\/([^\/]+)\/.*/)
name = ret[0].to_s + ".txt"
FileUtils.mv(path, name)
end
Years ago a friend wrote this and ran it from within a unix environment with success. When I run it now, an enormous number of errors are returned. I'm using Ruby 2.2.2 and it's entirely possible there's a placeholder somewhere that I'm too newbish to recognize, or perhaps something changed from the older version of FileUtils... I truly have no idea and am afraid I've been unable to turn up any answers with my neophyte skills.
And so I appeal to you...
Edit: Here's the error message:
C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1328:in `stat': Invalid argument # rb_file
_s_stat - ["may2013"].txt (Errno::EINVAL)
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1328:in `lstat'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1247:in `exist?'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:519:in `block in mv'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1570:in `block in fu_each_src
_dest'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1586:in `fu_each_src_dest0'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1568:in `fu_each_src_dest'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:516:in `mv'
from extracttxt.rb:12:in `block in <main>'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:48:in `block (2 levels) in find'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:47:in `catch'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:47:in `block in find'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:42:in `each'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:42:in `find'
from extracttxt.rb:6:in `<main>'
The error message shows that ret[0] is the array [ "may13" ], so ret[0].to_s + ".txt" evaluates to the string ["may13"].txt. I'm not sure, but it's possible the behavior of String#scan changed in Ruby 1.9 or 2.0, so it returns an array of arrays when captures are present, whereas before it returned an array of strings.
Something like this ought to solve the problem:
require 'find'
require 'fileutils'
Find.find("txts") do |path|
if FileTest.directory?(path)
next
end
if path =~ %r{txts/([^/]+)/}
FileUtils.cp(path, "#{$1}.txt")
end
end
If you want to match by file extension you could either add it to the Regexp above (e.g. %r{txts/([^/]+)/.+\.txt$}) or you could use Dir[] (a.k.a. Dir.glob) e.g.:
require 'dir'
require 'fileutils'
Dir['txts/**/*.txt'].each do |path|
next if FileTest.directory?(path) ||
next unless path =~ %r{txts/([^/]+)/}
FileUtils.cp(path, "#{$1}.txt")
end
I don't know if there will be any performance difference, but it might be worth trying.

Can't read a file that contains a question mark in name

I have a file with a name something like: /path/to/file/dir with spaces/mytiff-?.tif. In irb I try both the following:
open("/path/to/file/dir with spaces/mytiff-?.tif", 'rb')
File.open("/path/to/file/dir with spaces/mytiff-?.tif", 'rb')
And I'm getting an error:
Errno::ENOENT: No such file or directory.
I've also tried replacing the ? with \? in the string.
I'm using ruby 2.0.0. File is network drive (CIFS), client is a mac (lion).
Update
Thanks for the help. The problem is still not solved.
$ ls "/Volumes/rmrpp/MLP Library/Bridgland 1927 - North Saskatchewan/Stations/420/Repeat Masters/"
HIG2008_B27_420-100.tif HIG2008_B27_420-90.tif HIG2008_B27_420-92.tif HIG2008_B27_420-94.tif HIG2008_B27_420-96.tif HIG2008_B27_420-98.tif HIG2008_B27_420-?.tif
HIG2008_B27_420-101.tif HIG2008_B27_420-91.tif HIG2008_B27_420-93.tif HIG2008_B27_420-95.tif HIG2008_B27_420-97.tif HIG2008_B27_420-99.tif
$ irb
1.9.3p194 :001 > t = File.open("/Volumes/rmrpp/MLP Library/Bridgland 1927 - North Saskatchewan/Stations/420/Repeat Masters/HIG2008_B27_420-?.tif",'rb'); nil
Errno::ENOENT: No such file or directory - /Volumes/rmrpp/MLP Library/Bridgland 1927 - North Saskatchewan/Stations/420/Repeat Masters/HIG2008_B27_420-?.tif
from (irb):1:in `initialize'
from (irb):1:in `open'
from (irb):1
from /Users/mlp/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `<main>'
1.9.3p194 :002 > t = File.open("/Volumes/rmrpp/MLP Library/Bridgland 1927 - North Saskatchewan/Stations/420/Repeat Masters/HIG2008_B27_420-98.tif",'rb'); nil
=> nil
1.9.3p194 :003 > t.size
=> 50124180
As you can see, the file exists (I'm listing it in bash). I go into irb and try to read the file as a binary. The file path is quoted. It fails. I try another file from the same directory and it works.
I think #mu_is_too_short is correct. Maybe the ? isn't a question mark at all. The only viable solution I can think of is to manually rename the files with the mystery question mark. Any other ideas?
As long as the file exists, there is no problem opening a file like this:
folder_file = './temp directory/file-?.txt'
File.open(folder_file, 'r').close
This works fine.
See Tin Man's suggestion about how to actually open the .tif file.
As you can see, I created the following file myster-file_char?.txt
$: ls
get_listing.rb myster-file_char?.txt
You can get this stored in a variable, though I only use Dir.glob here to view it.
puts Dir.glob("**.*").inspect
Everything is now revealed in what character it is. Though I should be able to use it directly as is to open and edit the file in Ruby. Though like The Tin Man stated, you are asking about a binary file.
$: ruby get_listing.rb
["myster-file_char\u0016.txt", "get_listing.rb"]
The character that is actually there is a CTRLV. Hope this finally helps to unravel the mystery.

Runtime Error using Ruby FileUtils

I've been staring at this for hours, but am not sure what i'm doing wrong. I'm trying to write a simple script to move 100 or so files from various locations in an external list. Should be simple enough, and when I run the command through irb, everything works for that one file, but when running the script I get an error. Here's my script.
#! /opt/local/bin/ruby
require 'fileutils.rb'
list_of_files = File.read "files_to_copy.txt"
source_dir = "/Volumes/data/moved_from_share/"
dest_dir = "/Volumes/data/testeroooo/"
list_of_files.each do |line|
copy_from = source_dir + line
copy_to = dest_dir + line
puts copy_from
puts copy_to
puts
FileUtils.cp_r(copy_from, copy_to)
end
Here is some example input from "files_to_copy.txt":
Accounting HG/Accounts Payable/2011/2011_06/ebi_Inv_218876.pdf
Accounting HG/Accounts Payable/2011/2011_06/expeditors_1050006142.tif
Accounting HG/Accounts Payable/2011/2011_06/expeditors_7050627938.tif
And lastly, here is my output with error:
/Volumes/data/moved_from_share/Accounting PG/Accounts Payable/2011/2011_07/
/Volumes/data/testeroooo/Accounting PG/Accounts Payable/2011/2011_07/
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1255:in `copy': unknown file type: /Volumes/data/moved_from_share/Accounting PG/Accounts Payable/2011/2011_07/ (RuntimeError)
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:451:in `copy_entry'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1324:in `traverse'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:448:in `copy_entry'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:423:in `cp_r'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1395:in `fu_each_src_dest'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1411:in `fu_each_src_dest0'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1393:in `fu_each_src_dest'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:422:in `cp_r'
from copy_it.rb:14
from copy_it.rb:8:in `each'
from copy_it.rb:8
If you have any suggestions, I would love to hear them! Thank you!
Your file list likely contains Accounting PG/Accounts Payable/2011/2011_07/ as an entry, which is a Directory, not a File. This should work perfectly fine, as you're using cp_r.
You could override it to only copy files (assuming your file list includes the subfolder items too):
if File.file?(copy_from)
FileUtils.cp_r(copy_from, copy_to)
end

Resources