Why is "nil" being included in an array?

I'm trying to simply lower-case all of the files in a directory. It
doesn't work because RUBY complains about not being able to convert
"nil" to a string. Why in the world is it even including "nil" in my
array?

files = Dir.glob('*.pdf')
  files.each do |file|
  File.rename(file, file.downcase!)
end

It says:
"...can't convert nil into String (Type error)..."

Thanks,
Peter

···

--
Posted via http://www.ruby-forum.com/.

I think you're mistaking the source of your error here. Check this out
(ri String#downcase!):

    Downcases the contents of _str_, returning +nil+ if no changes were
    made.

So you're call to +downcase!+ is returning nil in the cases where
+file+ was already downcased. When +File.rename+ sees that nil and
tries to convert it to a String, it raises the error you see.

Try using +String#downcase+ instead (note the lack of the exclamation point).

Jacob Fugal

···

On 6/22/06, Peter Bailey <pbailey@bna.com> wrote:

I'm trying to simply lower-case all of the files in a directory. It
doesn't work because RUBY complains about not being able to convert
"nil" to a string. Why in the world is it even including "nil" in my
array?

files = Dir.glob('*.pdf')
  files.each do |file|
  File.rename(file, file.downcase!)
end

It says:
"...can't convert nil into String (Type error)..."

An excellent illustration of why side-effects can be harmful.

file.downcase! has to be evaluated before File.rename can be evaluated. #downcase! returns nil if no changes are made, so for any file that's already in lower case, you're making this call:

File.rename(file, nil)

You can fix this if you change the ! method to the normal #downcase. This will also help you avoid a more subtle bug:

files = Dir.glob('Test')
=> ["Test"]
files.each do |file|
   File.rename(file, file.downcase!)
end
files = Dir.glob('Test')
=> ["Test"] # What the hell? shouldn't that be gone?

It's the same bug biting you in a different way: this time, because #downcase! is evaluated before the call to #rename, it's modifying the file variable in-place, so #rename is effectively being called like this:

File.rename('test', 'test')

Where 'test' obviously doesn't exist in the first place (or even if it did, it's still not what you wanted).

matthew smillie.

···

On Jun 22, 2006, at 19:22, Peter Bailey wrote:

I'm trying to simply lower-case all of the files in a directory. It
doesn't work because RUBY complains about not being able to convert
"nil" to a string. Why in the world is it even including "nil" in my
array?

files = Dir.glob('*.pdf')
  files.each do |file|
  File.rename(file, file.downcase!)
end

I had no idea that Ruby evaluated it that way. Thank you for this
detailed explanation.

Pat

···

On 6/22/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

It's the same bug biting you in a different way: this time, because
#downcase! is evaluated before the call to #rename, it's modifying
the file variable in-place, so #rename is effectively being called
like this:

File.rename('test', 'test')

Jacob Fugal wrote:

···

On 6/22/06, Peter Bailey <pbailey@bna.com> wrote:

It says:
"...can't convert nil into String (Type error)..."

I think you're mistaking the source of your error here. Check this out
(ri String#downcase!):

    Downcases the contents of _str_, returning +nil+ if no changes were
    made.

So you're call to +downcase!+ is returning nil in the cases where
+file+ was already downcased. When +File.rename+ sees that nil and
tries to convert it to a String, it raises the error you see.

Try using +String#downcase+ instead (note the lack of the exclamation
point).

Jacob Fugal

I see. Thanks a lot, Jacob. There's danger in my scripting there. I'll
try it without the exclamation.

-Peter

--
Posted via http://www.ruby-forum.com/\.