finding all directories except hidden ones
I'm assuming you're classing directories that start with a dot as "hidden". To avoid descending into such directories you should use -prune
.
find . -mindepth 1 -type d \( -name '.*' -prune -o -print \)
This starts in the current directory (we could have specified *
here but that presupposes your wildcard is not set to include dot files/directories - for example bash
's dotglob
). It then matches only on directories, but not considering .
itself. The section in brackets tells find
that if the name matches .*
then it's to be pruned, so that neither it nor its descendants are to be considered further; otherwise print its name.
If you don't have the (non-POSIX) -mindepth
option you could use this alternative. Arguably this is better than the original solution I've suggested but I'm going to leave both in the answer
find . -type d \( -name '.?*' -prune -o -print \)
With zsh
:
print -rC1 -- **/*(N/)
(zsh globs skip hidden files by default).
Or to do anything with those dirs:
for dir (**/*(N/)) anything with $dir
or, if anything
can take more than one file at a time, with GNU xargs
or compatible:
xargs -r0a <(print -rNC1 -- **/*(N/)) anything with
POSIXly:
LC_ALL=C find . -name '.?*' -prune -o -type d -print
LC_ALL=C
is needed otherwise it would fail to skip hidden dirs whose name contains sequences of bytes that don't form valid character in the user's locale. See also how the order of the predicates makes sure we avoid applying -type d
(which potentially involves an extra expensive lstat()
system call) on those files whose name starts with .
.
That one also outputs .
(the current working directory), add a ! -name .
before -type
if you don't want it or change it to:
LC_ALL=C find . ! -name . \( -name '.*' -prune -o -type d -print \)
Do do anything with the files, replace -print
with -exec anything with {} ';'
or -exec anything with {} +
if anything
can take more than one file at once.
simply use:
find . ! -path '*/.*' -type d