开发者

How to use the .* wildcard in bash but exclude the parent directory (..)?

There are often times that I want to execute a command on all files (including hidden files) in a directory. When I try using

chmod g+w * .*

it changes the permissions on all the files I want (in the directory) and all the files in the parent directory (that I want left alone).

Is there a wildcard that does the right thing or do开发者_JS百科 I need to start using find?


You will need two glob patterns to cover all the potential “dot files”: .[^.]* and ..?*.

The first matches all directory entries with two or more characters where the first character is a dot and the second character is not a dot. The second picks up entries with three or more characters that start with .. (this excludes .. because it only has two characters and starts with a ., but includes (unlikely) entries like ..foo).

chmod g+w .[^.]* ..?*

This should work well in most all shells and is suitable for scripts.


For regular interactive use, the patterns may be too difficult to remember. For those cases, your shell might have a more convenient way to skip . and ... zsh always excludes . and .. from patterns like .*. With bash, you have to use the GLOBIGNORE shell variable.

# bash
GLOBIGNORE=.:..
echo .*

You might consider setting GLOBIGNORE in one of your bash customization files (e.g. .bash_profile/.bash_login or .bashrc). Beware, however, becoming accustomed to this customization if you often use other environments. If you run a command like chmod g+w .* in an environment that is missing your customization, then you will unexpectedly end up including . and .. in your command.

Additionally, you can configure the shells to include “dot files” in patterns that do not start with an explicit dot (e.g. *).

# zsh
setopt glob_dots

# bash
shopt -s dotglob


# show all files, even “dot files”
echo *


Usually I would just use . .[a-zA-Z0-9]* since my file names tend to follow certain rules, but that won't catch all possible cases.

You can use:

chmod g+w $(ls -1a | grep -v '^..$')

which will basically list all the files and directories, strip out the parent directory then process the rest. Beware of spaces in file names though, it'll treat them as separate files.

Of course, if you just want to do files, you can use:

find . -maxdepth 0 -type f -exec chmod g+w {} ';'

or, yet another solution, which should do all files and directories except the .. one:

for i in * .* ; do if [[ ${i} != ".." ]] ; then chmod g+w "$i"; fi done

but now you're getting into territory where scripts or aliases may be necessary.


What i did was

tar --directory my_directory --file my_directory.tar --create `ls -A mydirectory/`

Works just fine the ls -A my_directory expands to everything in the directory except . and ... No wierd globs, and on a single line.

ps: Perhaps someone will tell me why this is not a good idea. :p


How about:

shopt -s dotglob
chmod g+w ./* 


Since you may not want to set dotglob for the rest of your bash session you can set it for a single set of commands by running in a subprocess like so:

$ (shopt -s dotglob; chmod g+w ./*)


If you are sure that two character hidden file names will never be used, then the simplest option is just be to do:

chmod g+w * ...*
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜