我们团队中的某人想要递归地更改用户主目录中所有隐藏目录的用户权限。为此,他执行了以下命令:
cd /home/username
chown -R username:groupname .*
当我们意识到他实际上递归地更改了 /home 中所有用户目录的权限时,我们感到非常惊讶,因为也.*
等于。..
您是否预料到 Linux 中会出现这种行为?
答案1
当我尝试使用 .* 做任何事情时,我总是会被烧伤,并且很久以前就切换到使用字符类:
chown -R username.groupname .[A-Za-z]*
我就会这样做。
编辑:有人指出这不会得到,例如点文件,例如._Library
.要使用的捕获所有字符类是
chown -R username.groupname .[A-Za-z0-9_-]*
答案2
使用扩展通配符 ( shopt -s extglob
),您可以使用
.!(.|)
即点后面没有点或者什么都没有。
答案3
仅当该字符是文件名的第一个字符并且将由通配符匹配时,该字符.
才会从通配符匹配中排除。在模式 中.*
,*
匹配以 开头的字符串.
,因此.*
包含..
(以及.
,*
匹配空字符串)。这是模式匹配规则的直接结果,尽管它可能很烦人。
.
做出例外并系统地从匹配中排除和是有意义的..
,但这不是历史上的做法,很多 Bourne/POSIX shell(sh
、dash
、bash
、 AT&Tksh
等yash
)都包含它们, (t)csh 甚至也是如此鱼 1.x。一些 shell 将.
和排除..
在所有通配符匹配之外:zsh、pdksh/posh/mksh(与 AT&T ksh 不同)、fish≥2.0。
如果设置GLOBIGNORE
为任何非空值,巴什切换到从匹配中排除.
和的方便但非标准的行为。..
设置GLOBIGNORE
还会关闭排除点文件的行为;使用,您会得到排除点文件GLOBIGNORE='.*'
的通常行为,但仅匹配点文件而不匹配或。设置(或) 以匹配所有文件,包括点文件,但不包括和。./*
./.*
.
..
GLOBIGNORE=.:..
GLOBIGNORE=.
./*
.
..
在 ksh93 中,设置FIGNORE='@(.|..)'
为从匹配中排除.
和..
但包含点文件。因此.*
将扩展为点文件,但不包含.
或..
.
无需借助特定于 shell 的功能,您可以使用以下两个 glob 来匹配点文件:
.[!.]* ..?*
以及具有以下三个 glob 的所有文件(不包括.
和):..
..?* .[!.]* *
但您需要小心,因为一个或多个 glob 可能与任何文件都不匹配,这将导致相应的模式保持未展开状态。
为了避免意外,它可能更容易使用find
。find
永远不会递归到父目录(除非被告知遵循符号链接)。
find /home/username/. -name . -o -prune -name '.*' -exec chown -R username:groupname {} +
答案4
考虑使用find
(-maxdepth
是一个非 POSIX 扩展,但它应该可以在 Linux 上轻松使用):
find . -maxdepth 1 -type d -name '.*' -exec chown -R user:group {} +