75

I want to glob every hidden file and directory, but not the current (.) and parent directory (..).

I am using bash.

Observe current behaviour:

$ ls -a
.  ..  ...a  ...aa  ..a  ..aa  .a  .aa  .aaa  a
$ echo *
a
$ echo .*
. .. ...a ...aa ..a ..aa .a .aa .aaa

I would like .* to behave like this

$ echo .*
...a ...aa ..a ..aa .a .aa .aaa

There is the shell option dotglob

$ shopt -s dotglob

that works in a way; now I can use * to glob everything (hidden or not) but not . and ..

$ echo *
...a ...aa ..a ..aa .a .aa .aaa a

but now I can't differentiate between hidden or not. Also, .* still globs . and ..

$ echo .*
. .. ...a ...aa ..a ..aa .a .aa .aaa

Is there a way to make .* not expand to . and ..?

69

You can use the GLOBIGNORE variable to hide the . and .. directories. This does automatically also set the dotglob option, so * now matches both hidden and non-hidden files. You can again manually unset dotglob, though, this then gives the behavior you want.

See this example:

$ ls -a
.  ..  a  .a  ..a
$ GLOBIGNORE=".:.."
$ shopt -u dotglob
$ echo * # all (only non-hidden)
a
$ echo .* # all (only hidden)
.a ..a
| improve this answer | |
  • 1
    This only works if you include the glob in the command; env GLOBIGNORE=". .." ls -a returns . and .. but ... ls -ad .* doesn't. – gvkv Aug 24 '10 at 13:04
  • 2
    I don't get this comment... The question was not about the ls command, but about a glob -- "including the glob in the command" is exactly what the OP wanted to do... – Marcel Stimberg Aug 24 '10 at 13:31
  • It's informational not critical. – gvkv Aug 24 '10 at 13:48
  • 4
    No problem, I'm not afraid of criticism. It's just that I didn't understand the connection between the comment and my answer. But as I did also not understand your the connection between your answer and the original question that's consistent at least ;) – Marcel Stimberg Aug 24 '10 at 13:55
  • Yeah, I got caught up with trying to make extended globbing patterns work with . the way I think it should using ls as a canonical command and forgot about the details of the post. – gvkv Aug 24 '10 at 14:03
25

The first glob below requires a leading dot and at least one additional non-dot character. These two globs together will match any possible hidden files, including files with more than one leading dot, but not . or .., which is exactly what you asked for.

ls -ld .[!.]* ..?*
| improve this answer | |
  • 3
    That would also exclude ..foo. The portable syntax is .[!.]*. .[^.]* is not standard (though supported by many shells) – Stéphane Chazelas Jan 9 '14 at 10:20
  • 1
    @StephaneChazelas: Today I learned! Fixed. – bukzor Mar 10 '14 at 17:48
7

Are you just looking for files? Are you in a position to use find?

Something like (assuming GNU find):

find . -mindepth 1 -maxdepth 1 -name ".*" -printf "%P\n"
| improve this answer | |
  • Newline-delimiting can cause issues with filenames containing newlines; null-delimiting shouldn't. – Solomon Ucko Jul 26 '19 at 22:01
6

With zsh, fish, pdksh and at least some of its derivatives like mksh, posh:

echo .*

(the globs of those shells never expand . or .., which is the most sensible thing to do).

With bash:

shopt -s dotglob
echo [.]*

(with dotglob, . and .. are not expanded unless you use a glob that starts with a literal . as in .* or dir/.*, as otherwise things like chmod +rwx -- * would have unexpected consequences).

Or:

GLOBIGNORE=.
echo .*

(with bash, like for dotglob and for the same reason, as soon as GLOBIGNORE is non-empty, both . and .. are automatically ignored in globs not contains slashes (and dotglob is enabled) and this time even with a literal . as above. Note that GLOBIGNORE=/ for instance would have the same effect).

Note however that . and .. would still be included in globs like dir/.* or .*/file.

With ksh93

FIGNORE='@(.|..)'
echo .*
| improve this answer | |
5

You want to show hidden files/folders BUT . and .. ?

Use this bash wildcard {.[!.]*,..?*}

Sample Data

You can try by generating sample data :

$ touch ...a  ...aa  ..a  ..aa  .a  .aa  .aaa  a
$ mkdir ...b  ...bb  ..b  ..bb  .b  .bb  .bbb  b

Proof

Below you can see the expected removed entries :

$ diff <(\ls -a) <(\ls -ad {.[!.]*,..?*})
1,3d0
< .
< ..
< a
11d7
< b

Pro

Useful to delete all hidden elements for example :

$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'

# <regenerate sample data here>

$ rm -rf {.[!.]*,..?*}
# No error
  • 2
    with modern bash you can factor out * {.[!.],..?,}* – Pablo Marin-Garcia Jan 7 at 17:59
  • what is the point in using braces expansion vs .[!.]* ..?* (just a space between two globs)? – maoizm Oct 11 at 15:43
2

Try ls -A.  Here's an excerpt from the manual:

-A, --almost-all

    do not list implied . and ..

| improve this answer | |
  • Plus 1, I was looking for how to hide the . and .. files from the ls ouput and stumbled on your answer. Thanks a lot Orso Grigio :) – Forever Learner May 9 '17 at 13:05
  • Not exactly an answer to the original question, as it also lists non-hidden files, but exactly what I was looking for! – Griddo Oct 6 '18 at 9:37
-1
ls -1a|egrep -v '^(\.|\.\.)$'
| improve this answer | |
  • 2
    ls should never be parsed or used in scripts, and certainly not as a replacement to globbing. – MestreLion Mar 28 '13 at 7:19
  • Right, see mywiki.wooledge.org/ParsingLs for more information – ignis Apr 25 '13 at 9:45
  • Also, you don’t need to specify the -1 (one) option to ls when you’re piping the output or redirecting it into a file. – G-Man Says 'Reinstate Monica' Oct 11 at 21:23

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