1

Given the following directories structure:

$ tree --noreport dir

dir
├── fileA
├── .hiddenfileA
├── .hiddendirA
|   ├── .hiddenfileB
│   ├── fileC
│   └── fileD
└── dirA
    ├── .hiddenfileC
    ├── fileE
    └── fileF

The requirement is to make a call to find so that files from hidden directories but not hidden files (under not hidden directories) are excluded from the result.

The expected return should be something similar to:

./.hiddenfileA
./dirA/.hiddenfileC
./dirA/fileE
./dirA/fileF
./fileA

Did some research and found here information that led me to create the following call to find

$ find . -type f -not -path '*/\.*' -print

But this solution has the drawback that skips hidden directories and files.

2
  • Should a file at the path some/.dir/here/file be returned or not?
    – Kusalananda
    Dec 30, 2019 at 7:48
  • @Kusalananda Since it is under a hidden directory it should not be returned. Dec 30, 2019 at 15:47

2 Answers 2

4

Prune hidden directories and limit the results to files:

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

As suggested by jthill, you might prefer filtering out directories, which would result in showing files, links etc.:

find . -type d -name '.?*' -prune -o ! -type d -print
2
  • OCD squishification: find -type d -name '.?*' -prune -o -type f -- but you probably want to end with ! -type d instead of -type f so you get symbolic links and other less-usual types
    – jthill
    Nov 27, 2019 at 16:04
  • Thanks for the simplification! I was following the filter from the question. Nov 27, 2019 at 16:28
1

The command you have is very close to working.  Use

find . -type f ! -path '*/.*/*' -print
  • The path pattern, */.*/*, looks for a /. (implying a segment name that begins with .) followed (eventually) by a / — so the segment name that begins with . cannot be the last one (the file name); i.e., it must be a directory name.
  • -path uses filename expansion patterns; a.k.a. globs or wildcards.  So you don’t need to put \ before ..
  • Don’t use -not if you want portability to non-GNU systems.  The use of ! to represent “not” is specified by POSIX, and works in every version of find (even BSD, Solaris, etc., and ancient systems).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .