# Renaming Files

**URL:** <https://www.ruby-forum.com/t/renaming-files/112806>\
**Category:** Ruby\
**Created:** [August 23, 2007, 1:21pm UTC](https://www.ruby-forum.com/t/renaming-files/112806 "2007-08-23T13:21:22Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mobileamusement](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mobileamusement](https://www.ruby-forum.com/u/mobileamusement)\
**Post date:** [August 23, 2007, 1:21pm UTC](https://www.ruby-forum.com/t/renaming-files/112806/1 "2007-08-23T13:21:22Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![mobileamusement](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mobileamusement](https://www.ruby-forum.com/u/mobileamusement)\
**Post date:** [August 23, 2007, 1:28pm UTC](https://www.ruby-forum.com/t/renaming-files/112806/2 "2007-08-23T13:28:22Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![mobileamusement](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mobileamusement](https://www.ruby-forum.com/u/mobileamusement)\
**Post date:** [August 23, 2007, 1:30pm UTC](https://www.ruby-forum.com/t/renaming-files/112806/3 "2007-08-23T13:30:22Z")

</div>

Alle giovedì 23 agosto 2007, Gabriel D. 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

---

<div class="post-metadata">

**Author:** ![mobileamusement](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mobileamusement](https://www.ruby-forum.com/u/mobileamusement)\
**Post date:** [August 23, 2007, 1:48pm UTC](https://www.ruby-forum.com/t/renaming-files/112806/4 "2007-08-23T13:48:26Z")

</div>

On 23 Aug 2007, at 12:27, Peter H. wrote:

> 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

---

<div class="post-metadata">

**Author:** ![mobileamusement](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mobileamusement](https://www.ruby-forum.com/u/mobileamusement)\
**Post date:** [August 23, 2007, 1:55pm UTC](https://www.ruby-forum.com/t/renaming-files/112806/5 "2007-08-23T13:55:26Z")

</div>

Alle giovedì 23 agosto 2007, Gabriel D. 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

---

<div class="post-metadata">

**Author:** ![mobileamusement](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mobileamusement](https://www.ruby-forum.com/u/mobileamusement)\
**Post date:** [August 23, 2007, 2:31pm UTC](https://www.ruby-forum.com/t/renaming-files/112806/6 "2007-08-23T14:31:32Z")

</div>

On 23 Aug 2007, at 12:54, Stefano C. wrote:

> 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.

---

<div class="post-metadata">

**Author:** ![mobileamusement](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mobileamusement](https://www.ruby-forum.com/u/mobileamusement)\
**Post date:** [August 23, 2007, 2:34pm UTC](https://www.ruby-forum.com/t/renaming-files/112806/7 "2007-08-23T14:34:32Z")

</div>

Hi,

Am Donnerstag, 23. Aug 2007, 20:29:26 +0900 schrieb Stefano C.:

> Alle giovedì 23 agosto 2007, Gabriel D. 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
