6

I want to check if pattern with wildcards, e.g. /var/data/**/*.xml is matching to any file or directory on the disk.

Obviously I could use Dir.glob but it is very slow when there are millions of files because it is too eager - it returns all files matching the pattern while I only need to know if there is any.

Is there any way I could check that?

1

1 Answer 1

5

Ruby-only

You could use Find, find and find :D.

I couldn't find any other File/Dir method that returns an Enumerator.

require 'find'
Find.find("/var/data/").find{|f| f=~/\.xml$/i }
#=> first xml file found inside "/var/data". nil otherwise
# or
Find.find("/var/data/").find{|f| File.extname(f).downcase == ".xml" }

If you really just want a boolean :

require 'find'
Find.find("/var/data/").any?{|f| f=~/\.xml$/i }

Note that if "/var/data/" exists but there is no .xml file inside it, this method will be at least as slow as Dir.glob.

As far as I can tell :

Dir.glob("/var/data/**/*.xml"){|f| break f}

creates a complete array first before returning its first element.

Bash-only

For a bash-only solution, you could use :

Sign up to request clarification or add additional context in comments.

4 Comments

I'm afraid that find is not a solution for me. Path pattern that I have to check is in fact entered by the user and later passed to find shell command. The final effect that I want to achieve is to avoid no such file or directory error when executing find (from shell, not ruby Find.find)
stackoverflow.com/questions/2937407/… It looks like shell find might be the best option, followed by compgen.
Thank you, compgen works very well. It is not perfect, as it is bash-only solution, but fortunately it is available on all machines that I'm using.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.