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)…”
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).
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
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).
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’)
I had no idea that Ruby evaluated it that way. Thank you for this
detailed explanation.
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 F.
I see. Thanks a lot, Jacob. There’s danger in my scripting there. I’ll
try it without the exclamation.
-Peter
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.