# Directory tree traversal fun

**URL:** <https://www.ruby-forum.com/t/directory-tree-traversal-fun/106877>\
**Category:** Ruby\
**Created:** [June 14, 2007, 10:47pm UTC](https://www.ruby-forum.com/t/directory-tree-traversal-fun/106877 "2007-06-14T22:47:59Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jerry\_Blanco](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/a587f6/32.png) [@Jerry\_Blanco](https://www.ruby-forum.com/u/Jerry_Blanco)\
**Post date:** [June 14, 2007, 10:47pm UTC](https://www.ruby-forum.com/t/directory-tree-traversal-fun/106877/1 "2007-06-14T22:47:59Z")

</div>

Hi,  
I want to write a recursive file renamer. It will work such that given  
the following:

c:\prov\foo1.txt  
c:\prov\fooDir  
c:\prov\fooDir\foo2.txt

you call rename(“c:\prov”, “foo”, “bar”) and get

c:\prov\bar1.txt  
c:\prov\barDir  
c:\prov\barDir\bar2.txt

I wrote the following:

def rename(headOfTree, what, withWhat)  
p = Pathname.new(headOfTree)  
p.find() do |file|  
path = file.to\_s #just to make it prettier  
File.rename(path, path.gsub("#{what}", withWhat)) if  
path.include?(what)  
end  
end

The problem is that p.find() is top-to-bottom, so it renames in the  
following order:

1. c:\prov\bar1.txt
2. c:\prov\barDir

Then, it can’t get to c:\prov\fooDir anymore, so it doesn’t rename  
c:\prov\fooDir\foo2.txt

Is there a more elegant solution than creating an array with the  
names, sort the array length descending and rename? I don’t trust this  
approach because it could happen that it reverts the order of some  
files.

Is there a way to traverse a directory leaves-first? (bottom-to-top)

---

<div class="post-metadata">

**Author:** ![Jerry\_Blanco](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/a587f6/32.png) [@Jerry\_Blanco](https://www.ruby-forum.com/u/Jerry_Blanco)\
**Post date:** [June 14, 2007, 11:58pm UTC](https://www.ruby-forum.com/t/directory-tree-traversal-fun/106877/2 "2007-06-14T23:58:24Z")

</div>

On Jun 14, 2007, at 1:47 PM, Jerry Blanco wrote:

> Hi,  
> Hi.

> def rename(headOfTree, what, withWhat)  
> p = Pathname.new(headOfTree)  
> p.find() do |file|  
> path = file.to\_s #just to make it prettier  
> File.rename(path, path.gsub("#{what}", withWhat)) if path.include?  
> (what)  
> end  
> end

> Is there a way to traverse a directory leaves-first? (bottom-to-top)

def rename( headOfTree, what, withWhat )  
p = Pathname.new( headOfTree )  
p.each\_entry do |file|  
path = file.to\_s #just to make it prettier  
next if path =~ /^..?$/  
rename( path, what, withWhat ) if path.directory?  
File.rename( path, path.gsub( “#{what}”, withWhat ) ) if  
path.include?( what )  
end  
end

This code is untested, but if you recurse before you rename, you  
should get what you want.
