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.

  • Should a file at the path some/.dir/here/file be returned or not? – Kusalananda Dec 30 '19 at 7:48
  • @Kusalananda Since it is under a hidden directory it should not be returned. – Paulo Tomé Dec 30 '19 at 15:47
5

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
  • 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 '19 at 16:04
  • Thanks for the simplification! I was following the filter from the question. – Stephen Kitt Nov 27 '19 at 16:28
0

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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.