33

I want to carry out some action (say chown) on all the hidden files in a directory.

I know that this .* is not a good idea because it will also find the current . and parent .. directories (I know that rm will fail to operate on . and .. but other commands, including chown and chmod, will happily take effect)

But all my hidden files have different names!

How should I glob for all hidden files while excluding . and .. ?

0

4 Answers 4

33

In Bash, set the GLOBIGNORE variable as follows:

GLOBIGNORE=".:.."

to hide the . and .. directories. This also sets the dotglob option so that the glob * character now matches both hidden and non-hidden files. Setting the GLOBIGNORE variable as shown above only affects the current terminal session and top-level processes unless you export it and and add it to your ~/.bashrc file as export GLOBIGNORE=".:..".

You can also do:

shopt -s dotglob

Source: Gilles' answer here :)

1
  • 3
    IMO this is better than the accepted answer. Easier to remember, infinitely more intuitive, and able to be stuffed into .bashrc to make it permanent if one so wishes (I know I almost never want * to mean "non-dotfiles only").
    – jcgoble3
    Sep 27, 2021 at 4:30
22

You can use the following extglob pattern:

.@(!(.|))
  • . matches a literal . at first

  • @() is a extglob pattern, will match one of the patterns inside, as we have only one pattern inside it, it will pick that

  • !(.|) is another extglob pattern (nested), which matches any file with no or one .; As we have matched . at start already, this whole pattern will match all files starting with . except . and ...

extglob is enabled on interactive sessions of bash by default in Ubuntu. If not, enable it first:

shopt -s extglob

Example:

$ echo .@(!(.|))
.bar .foo .spam
6
  • 1
    This is clearly an awesome thing I need to learn about! Thank you for teaching
    – Zanna
    Sep 26, 2016 at 10:38
  • @Zanna Glad i could help :)
    – heemayl
    Sep 26, 2016 at 10:39
  • 2
    What is the purpose of the @()? Simple .!(.|) seems to work identically. Sep 26, 2016 at 16:49
  • 1
    I know that this is old, but I have the same question as @KyleStrand. In my tests, !(.|) works the same. Is there any purpose behind @() in this context? Apr 2, 2017 at 7:26
  • 1
    @userunknown, right, !() means to not match any of the pipe-separated alternatives inside of it, so basically this is saying: match a dot, but do not let the second character match a dot or an empty string. As pointed out above, the @() which means to pick only one of the pipe-separated alternatives, does not have a purpose since there are no alternatives. My golden source for glob information is this primer from node-glob (See github.com/isaacs/node-glob#glob-primer) which is equivalent to enabling dotglob in the shell Jan 29, 2023 at 14:47
10

You can use a find command here. For example something like

find -type f -name ".*" -exec chmod 775 {} \;

This will find hidden files and change permissions


Edit to include the comment by @gerrit:

find -type f -maxdepth 1 -name ".*" -exec chmod 775 {} \;

This will limit the search top the current directory instead of searching recursively.

0
3

In case anyone need an alternative that doesn't require environment variables or shell options enabled like dotglob or extglobyou can use the following:

.[!.]*

it works because it matches at least two characters, the second of which must not be a dot (.)

I came to this question because I was looking for a way to match dotfiles and non-dotfiles, for which you could use:

{.[!.]*,*}

which matches either of the two options.

I needed a glob that didn't require environment variables nor shell options; and the reason is that I needed a glob that worked in VSCode's findFiles API, which supports globs (See https://code.visualstudio.com/api/references/vscode-api#3906), but doesn't offer room for shell options nor dotglob or extglob equivalents. It is nice that these tools decided to use the *NIX way for doing globs.

You must log in to answer this question.

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