Kevin R.
Kevin R.

Reputation: 602

How to iterate over two directories

I suspect this is the reason why I might be doing a file by file comparison too many times

I have two directories: directory1 contains files foo.txt and bar.txt, and directory2 contains files foo.txt and bar.txt as well.

def process(directory1, directory2)
  Dir.foreach(directory1) do |file1|
    Dir.foreach(directory2) do |file2|
      puts file1 + file2
    end
  end
end

When I run this I get:

..
...
.foo.txt
.bar.txt
...
....
..foo.txt
..bar.txt
foo.txt.
foo.txt..
foo.txtfoo.txt
foo.txtbar.txt
bar.txt.
bar.txt..
bar.txtfoo.txt
bar.txtbar.txt

It should be only printing four names. Is my loop wrong?

Upvotes: 1

Views: 167

Answers (3)

Noman Ur Rehman
Noman Ur Rehman

Reputation: 6957

In Linux, there are also the . and .. files in a directory.

By having foo.txt and bar.txt, you actually have 4 files in both the directories.

That is why your loop is printing 16 filenames as 4x4=16

You can confirm this by executing the ls -a command inside either of the directories.

Upvotes: 1

engineersmnky
engineersmnky

Reputation: 29318

To answer the actual question in your title you can iterator over 2 directories using Dir::[] e.g.

Dir['/directory1/*','/directory2/*'] 

This will return an Array of the files and directories located directly under /directory1 and /directory2. Also this will ignore dot files.

See Dir#glob for additional pattern options like recursion (**).

Upvotes: 2

derekerdmann
derekerdmann

Reputation: 18252

A little indentation makes the problem a little clearer:

def process(directory1, directory2)
  Dir.foreach(directory1) do |file1|
    Dir.foreach(directory2) do |file2|
      puts file1 + file2
    end
  end
end

For each item in directory1, you're printing each item in directory2.

I'm not entirely sure how you're trying to use these files or why you're adding the names together in your example, but splitting these into 2 separate loops would be enough to hit each file once.

The other part that may be surprising here is that "." and ".." appear as files when you loop over these directories. That's because "." is a placeholder file that represents the current directory and ".." represents the parent directory just like when you're using a command line, but Ruby also includes them when you enumerate directories this way.

Upvotes: 2

Related Questions