Starting from (notice the wildcards before and after "some text")
find . -type f -name '*some text*'
how can one exclude/ignore all hidden files and directories?
I've already been googling for far too long, came across some -prune and ! (exclamation mark) parameters, but no fitting (and parsimonious) example which just worked.
Piping |
to grep
would be an option and I'd also welcome examples of that; but primarily I'm interested in a brief one-liner (or a couple of stand-alone one-liners, illustrating different ways of achieving the same command-line goal) just using find
.
ps: Find files in linux and exclude specific directories seems closely related, but a) is not accepted yet and b) is related-but-different-and-distinct, but c) may provide inspiration and help pinpoint the confusion!
Edit
find . \( ! -regex '.*/\..*' \) -type f -name "whatever"
, works. The regex looks for "anything, then a slash, then a dot, then anything" (i.e. all hidden files and folders including their subfolders), and the "!" negates the regex.
This prints all files that are descendants of your directory, skipping hidden files and directories:
So if you're looking for a file with
some text
in its name, and you want to skip hidden files and directories, run:Explanation:
The
-path
option runs checks a pattern against the entire path string.*
is a wildcard,/
is a directory separator,.
is a dot (hidden filenames start with a dot on Linux), and*
is another wildcard.-not
means don't select files that match this test.I don't think that
find
is smart enough to avoid recursively searching hidden directories in the previous command, so if you need speed, use-prune
instead, like this:This is one of the few means of excludes dot-files that also works correctly on BSD, Mac and Linux:
$PWD
print the full path to the current directory so that the path does not start with./
-name ".*" -prune
matches any files or directories that start with a dot and then don't descend-o -print
means print the file name if the previous expression did not match anything. Using-print
or-print0
causes all other expressions to not print by default.You don't have to use
find
for that. Just use globstar in shell it-self, like:or:
where
**/
represents any folder recursively and*foo*
any file which hasfoo
in its name.By default using
ls
will print file names excluding hidden files and directories.If you don't have globbing enabled, do it by
shopt -s globstar
.Note: A new globbing option works in Bash 4, zsh and similar shells.
Example:
Excludes all hidden directories, and hidden files under $DIR
The answer I originally posted as an "edit" to my original question above:
find . \( ! -regex '.*/\..*' \) -type f -name "whatever"
, works. The regex looks for "anything, then a slash, then a dot, then anything" (i.e. all hidden files and folders including their subfolders), and the "!" negates the regex.@Flimm's answer is good, particularly because it prevents find from descending into hidden directories. I prefer this simplification:
Generally to exclude all hidden paths (regular files, directories, etc):
For example, using your working directory as the start point, and
-name '*some text*'
as the expression:In contrast to what @Flimm's answer suggests, no hidden files or hidden directories is the simple case. The
-path '*/.*'
expression is true for any path (regular files, directories, etc) that has a.
immediately after your file separator,/
. So this line will prune both hidden files and directories.Allowing hidden files while excluding hidden directories is the case that requires a further filter. This is where you would include
-type d
in the the expression being pruned.For example:
In this case
-type d -path '*/.*'
istrue
only for directories, and so only directories are pruned.This usually works too
Using * shell wildcard for input all paths from working directory, usually * wildcard doesn't expand to hidden files but this could be changed in the shell options. Example:
A variant on https://askubuntu.com/a/749708/321070
Instead of setting the directory to a full path, instead filter out things that mat ch
.?*
- a literal dot, any character, and then 0 or more characters.find
has neat logic switches such as-and
and-not
you can use them to your advantage to find a matching file with two rules like so:As you can see,
find
uses two rules-name '*hidden_file*'
and-and \( -not -name ".*" \)
to find those filenames that match both conditions - filename withhidden_file
in it but without leading dot. Note the slashes in front of parenthesis - they are used to define parenthesis asfind
arguments rather defining a subshell (which is what parenthesis mean otherwise without slashes)Notes:
.
: current folder-maxdepth 1
to search recursively-type f
: find files, not directories (d
)-not -path '*/\.*'
: do not return.hidden_files
sed 's/^\.\///g'
: remove the prepended./
from the result list