Reputation: 694
I am trying to learn ruby(1.8.7). I have programmed in php for some time and I consider myself proficient in that language. I have a book which I reference, and I have looked at many introductory ruby tutorials, but I cannot figure this out.
myFiles = ['/Users/', '/bin/bash', 'Phantom.file']
myFiles.each do |cFile|
puts "File Name: #{cFile}"
if File.exists?(cFile)
puts "#{cFile} is a file"
cFileStats = File.stat(cFile)
puts cFileStats.inspect
cFileMode = cFileStats.mode.to_s()
puts "cFileMode Class: " + cFileMode.class.to_s()
puts "length of string: " + cFileMode.length.to_s()
printf("Mode: %o\n", cFileMode)
puts "User: " + cFileMode[3,1]
puts "Group: " + cFileMode[4,1]
puts "World: " + cFileMode[5,1]
else
puts "Could not find file: #{cFile}"
end
puts
puts
end
produces the following output:
File Name: /Users/
/Users/ is a file
#<File::Stat dev=0xe000004, ino=48876, mode=040755, nlink=6, uid=0, gid=80, rdev=0x0, size=204, blksize=4096, blocks=0, atime=Sun Sep 04 12:20:09 -0400 2011, mtime=Thu Sep 01 21:29:08 -0400 2011, ctime=Thu Sep 01 21:29:08 -0400 2011>
cFileMode Class: String
length of string: 5
Mode: 40755
User: 7
Group: 7
World:
File Name: /bin/bash
/bin/bash is a file
#<File::Stat dev=0xe000004, ino=8672, mode=0100555, nlink=1, uid=0, gid=0, rdev=0x0, size=1371648, blksize=4096, blocks=1272, atime=Sun Sep 04 16:24:09 -0400 2011, mtime=Mon Jul 11 14:05:45 -0400 2011, ctime=Mon Jul 11 14:05:45 -0400 2011>
cFileMode Class: String
length of string: 5
Mode: 100555
User: 3
Group: 3
World:
File Name: Phantom.file
Could not find file: Phantom.file
Wh is the string length different than expected? (Should be 5 for users, 6 for /bin/bash)? Why are the substrings not puling the correct characters. I understand World not being populated when referencing a 5 character string, but the offsets seem off, and in the case of /bin/bash 3 does not even appear in the string.
Thanks
Scott
Upvotes: 1
Views: 129
Reputation: 84180
This is a nice one.
When a number is preceeded by a 0, it is represented as octal. What you are actually getting for bin/bash:
0100755 to decimal = 33261
"33261".length = 5
And for /Users:
040755 to decimal = 16877
"16877".length = 5
Add the following line:
puts cFileMode
And you will see the error.
to_s takes an argument which is the base. If you call to_s(8) then it should work.
cFileMode = cFileStats.mode.to_s(8)
EDIT
files = ['/home/', '/bin/bash', 'filetest.rb']
files.each do |file|
puts "File Name: #{file}"
if File.exists?(file)
puts "#{file} is a file"
file_stats = File.stat(file)
puts file_stats.inspect
file_mode = file_stats.mode.to_s(8)
puts "cFileMode Class: #{file_mode.class}"
p file_mode
puts "length of string: #{file_mode.length}"
printf("Mode: #{file_mode}")
puts "User: #{file_mode[-3,1]}"
puts "Group: #{file_mode[-2,1]}"
puts "World: #{file_mode[-1,1]}"
else
puts "Could not find file: #{file}"
end
puts
puts
end
Upvotes: 3
Reputation: 40333
Instead of this:
puts "length of string: " + cFileMode.length.to_s()
What you want is this:
puts "length of string: #{cFile.length}"
Please do not use camel case for variables in Ruby, camel case is used on class names only, method and variable names should be written with underscores to separate multiple words.
It's also a good practice to avoid adding parameters to method calls that do not have parameters, so, instead of calling to_s() you should use to_s only.
Upvotes: 1