40

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

crantok
  • 105
  • 3
Zanna
  • 72,312

4 Answers4

39

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

Gabriel Staples
  • 11,502
  • 14
  • 97
  • 142
Rinzwind
  • 309,379
24

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
heemayl
  • 93,925
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.

Wayne_Yux
  • 4,942
6

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.