0

Consider following directory structure:

$ find m
m
m/f.sh
m/.a

I want to find hidden files in non-hidden directories with:

find . -not -path "*/.*" -and -name "*.*"
.
./m/f.sh

but only f.sh is found, where I expect to find also .a. When searching without -not -path part, all hidden files are found:

find . -name "*.*"
./m/f.sh
./m/.a

How can I specify to search non-hidden directories, but match also hidden files?

To clarify:

  • ./non-hidden-dir/.hidden-dir/.hidden-file should be found.
  • ./.hidden-dir/non-hidden-dir/.hidden-file should not be found.
Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202
l00p
  • 143
  • 1
  • 7
  • @KamilMaciorowski I think it complicates the question. I simply want to find hidden files in non-hidden directories. When searched without `-not -path` part but with "*.*" pattern for `-name` hidden files are displayed as well. Please see edited question. – l00p Nov 21 '20 at 08:34
  • You're not helping me helping you. Please answer "yes" or "no": (1) Should `./non-hidden-dir/.hidden-dir/.hidden-file` be found? (2) Should `./.hidden-dir/non-hidden-dir/.hidden-file` be found? – Kamil Maciorowski Nov 21 '20 at 08:54
  • @KamilMaciorowski 1) yes; 2) no; – l00p Nov 21 '20 at 09:31
  • So the top level subdirectory is the one that counts. Somewhat surprising but so be it. – Kamil Maciorowski Nov 21 '20 at 09:36

1 Answers1

1

About what you tried:

  • -not -path "*/.*" evaluates to false for any pathname containing /.. It excludes all hidden files and prunes all hidden subdirectories (not like -prune because their content will be tested, still the test will always turn out false).
  • -name "*.*" evaluates to true for any basename containing ., regardless if the dot appears in front (.a) or somewhere else (f.sh).

It seems you want to prune top level directories that are hidden. Everywhere else you want to find hidden files. So this:

find . -path './.*' -prune -o -name '.*'

The above code effectively treats . as non-hidden and it uses the POSIX definition of "file" which says a directory is also a file. If you meant "hidden regular files" then the code should be:

find . -type d -path './.*' -prune -o -type f -name '.*' -print

Notes:

  • -not and -and you used are not portable; the portable equivalents are ! and -a respectively (and you may or may not omit -a).
  • This answer of mine may be helpful in learning how find works.
Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202