[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Renaming Files

Gabriel Dragffy

8/23/2007 11:20:00 AM

Hi, I'm just trying to rename a whole load of files in a directory.
Been palying with IRB. My code doesn't work, no doubt because I
fluffed it.

irb(main):041:0> Dir.entries('.').each do |f|
irb(main):042:1* next if f=="." or f==".."
irb(main):043:1> File.move( f, f.gsub!( /\s/, '_' ) )
irb(main):044:1> end
Errno::ENOENT: No such file or directory -
Animating_Reality_2pm_26th_July_2007.MP3
from /opt/local/lib/ruby/1.8/ftools.rb:106:in `stat'
from /opt/local/lib/ruby/1.8/ftools.rb:106:in `move'
from (irb):43
from (irb):41:in `each'
from (irb):41
from :0

What's the best way of doing this, please?

Regards

Gabriel

6 Answers

Peter Hickman

8/23/2007 11:27:00 AM

0

The problem here is the ! on the gsub. This is changing the contents of
f *before* it gets passed to the function:

def show(a, b)
puts "[#{a}] [#{b}]"
end

x = "Here is a string"

show(x, x.gsub!(/\s/,'_'))

results in

[Here_is_a_string] [Here_is_a_string]

But change the gsub! to a plain gsub and you get

[Here is a string] [Here_is_a_string]

because a plain gsub returns a copy of the modified string without
modifying the original.

Only use the ! versions when you are absolutely sure you need to.


Stefano Crocco

8/23/2007 11:29:00 AM

0

Alle giovedì 23 agosto 2007, Gabriel Dragffy ha scritto:

> irb(main):043:1> File.move( f, f.gsub!( /\s/, '_' ) )

You need gsub, not gsub!. gsub! modifies the string it's called on (f), so
File.move the modified string also as first argument. And, since a file with
the modifed name doesn't exist, it raises an exception. Besides, gsub! will
return nil if no replacement happens (i.e, if f doesn't contain spaces). This
would also result in an exception. gsub, instead, creates a new string and
modifies it, so File.move receives two different strings.

I hope this helps

Stefano

Gabriel Dragffy

8/23/2007 11:47:00 AM

0


On 23 Aug 2007, at 12:27, Peter Hickman wrote:

> The problem here is the ! on the gsub. This is changing the
> contents of f *before* it gets passed to the function:
>
> def show(a, b)
> puts "[#{a}] [#{b}]"
> end
>
> x = "Here is a string"
>
> show(x, x.gsub!(/\s/,'_'))
>
> results in
>
> [Here_is_a_string] [Here_is_a_string]
>
> But change the gsub! to a plain gsub and you get
>
> [Here is a string] [Here_is_a_string]
>
> because a plain gsub returns a copy of the modified string without
> modifying the original.
>
> Only use the ! versions when you are absolutely sure you need to.
>
>

Thank you so much for these replies (Peter & Stefano). That makes
perfect sense. As soon as you pointed out gsub! was doing what is was
supposed to :)
Thanks. I just renamed a directory of about 30 files in 0.5 seconds
with that one.

Just another quicky, if I wanna rename all the files in the directory
is what I did OK, using:
next if f=="." or f==".."

I just feel there must a better way?

Best regards Gabriel

Stefano Crocco

8/23/2007 11:55:00 AM

0

Alle giovedì 23 agosto 2007, Gabriel Dragffy ha scritto:
> Just another quicky, if I wanna rename all the files in the directory  
> is what I did OK, using:
>         next if f=="." or f==".."
>
> I just feel there must a better way?

If you want to rename only files, then you should do

next unless File.file? f

This way, you skip not only the given directory and its parent, but also any
directory inside the current. If you're sure the given directory contains
only files, then you're approach and mine should be equivalent (although, in
my opinion, mine makes clearer why you're skipping those entries).

Stefano

Gabriel Dragffy

8/23/2007 12:31:00 PM

0


On 23 Aug 2007, at 12:54, Stefano Crocco wrote:

> Alle giovedì 23 agosto 2007, Gabriel Dragffy ha scritto:
>> Just another quicky, if I wanna rename all the files in the directory
>> is what I did OK, using:
>> next if f=="." or f==".."
>>
>> I just feel there must a better way?
>
> If you want to rename only files, then you should do
>
> next unless File.file? f
>
> This way, you skip not only the given directory and its parent, but
> also any
> directory inside the current. If you're sure the given directory
> contains
> only files, then you're approach and mine should be equivalent
> (although, in
> my opinion, mine makes clearer why you're skipping those entries).
>
> Stefano
>

Aha yes, perhaps in my situation both equal, but yours is surely
cleaner and in another situation it would save me from nuking the
subdirs. Thank you, Stefano.

Bertram Scharpf

8/23/2007 12:32:00 PM

0

Hi,

Am Donnerstag, 23. Aug 2007, 20:29:26 +0900 schrieb Stefano Crocco:
> Alle giovedì 23 agosto 2007, Gabriel Dragffy ha scritto:
> > irb(main):043:1> File.move( f, f.gsub!( /\s/, '_' ) )
>
> You need gsub, not gsub!. [...] gsub, instead, creates a new string and
> modifies it, so File.move receives two different strings.

I suppose the evaluation order of arguments is left to right
and f is handed over to File#move as long as it is the old
version. Yet, before is gets used it becomes modified by its
gsub! method.

Independently from such considerations it is never a good
idea to rely on evaluation orders anywhere else than in
and/&&/or/|| expressions. If File#move were a method taking
a block it surely were no good programming style either to
modify f inside that:

some_method( f) do ... ; f.gsub! ... ; ... end

This is admittedly not a beginners topic and probably far
from what Gabriel expected to meet.

Bertram


--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-...