How to list directory contents including dotfiles but not . and ..?
Asked Answered
I

3

19

How do I get Dir['*'] to include dotfiles, e.g., .gitignore, but not . and ..?

I.e., is there a better way to do:

`ls -A`.split "\n"

perhaps with Dir? The following solutions are close but both include . & ..:

Dir.glob('*', File::FNM_DOTMATCH)
Dir['{.*,*}']

So, the following works:

Dir.glob('*', File::FNM_DOTMATCH) - ['.', '..']

But, is there still a better way to do this?

I'm wondering this to fix line 9 of a Meteor Homebrew Formula.

Immortalize answered 8/7, 2012 at 18:58 Comment(5)
You've essentially edited your answer with the solution between me starting to answer and answering… :PRanjiv
What about Dir.glob(“{*,.*}”)?Gambrell
@Gambrell cool. I just noticed that myself from reading the Dir::glob Ruby Documentation and added it to my question. It also includes the . & .. entries.Immortalize
@AndrewMarshall ls -A excludes . & .. on OS X. Perhaps, you're thinking of ls -a?Immortalize
@MattDiPasquale I have ls aliased to ls -aFh and didn't do \ls -A …whoops. Realized it after the fact though and deleted the (wrong) comment.Ranjiv
R
21

You can't with Dir[], but you can with Dir.glob, which Dir[] calls:

Dir.glob("*", File::FNM_DOTMATCH)

You can get rid of the . & .. easily:

Dir.glob("*", File::FNM_DOTMATCH).tap { |a| a.shift(2) }

But I think it’s probably best to stick with your original way:

Dir.glob("*", File::FNM_DOTMATCH) - %w[. ..]

(among other ways)

However, if you don’t require a more sophisticated glob than *, Dir#children may be all you need (can always further filter/grep the results if more filtering is needed):

Dir.children('.')
Ranjiv answered 8/7, 2012 at 19:1 Comment(5)
Better than tap... might be reject { |a| a =~ /^\.{1,2}$/ }, which is more informative and also does not depend upon the order of the directory entries.Wyeth
@WayneConrad Yea I just did it quickly as the OP edited their question in rapid-fire mode. the best way is probably the array difference ... - %w[. ..]. The regex needed for the reject seems too dense for what is actually somewhat simple (not like my code was much clearer about the goal though :P)Ranjiv
tap is a pretty cool method though. :) But, good point, I'll stick with array difference for now. Thanks. :)Immortalize
@Matt - Oh, Array difference is way better than reject.Wyeth
You can also reject !File.file?( x ) as a way to reject . and .. if you don't mind ignoring directories.Example
C
3

Here's a shorter version:

Dir['{.[^\.]*,*}']
Clothesline answered 3/12, 2013 at 16:12 Comment(2)
This wouldn't match a file such as ..foobar.Beech
Why would you want to match ..foobar? .DOT files/folders are normal part of a file system listings (especially on linux/mac which use extFS), ..foobar would be an unlikely edgecaseSchumann
P
0

Here is how I did it to find all files in a directory including hidden files and remove .git/, ., .., and directories:

      files = Dir.glob("#{ARGV.first}/**/*", File::FNM_DOTMATCH)
      files = files.grep_v(/\/.git\//).grep_v(/\/\.$/).grep_v(/\/\.\.$/)
      files = files.select { |file| File.file?(file) }
Pasteurization answered 20/11, 2021 at 0:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.