Answers:
Bash,ksh和zsh有更好的解决方案,但是在这个答案中,我假设使用POSIX shell。
该模式.[!.]*
匹配所有以点后跟非点字符开头的文件。(请注意,[^.]
某些外壳程序(但并非所有外壳程序都支持[!.]
),通配符模式中字符集补码的可移植语法为。)因此,它排除了.
和..
,而且还排除了以两个点开头的文件。该模式..?*
处理以两个点开头并且不只是的文件..
。
chown -R root .[!.]* ..?*
这是设置为匹配所有文件的经典模式:
* .[!.]* ..?*
这种方法的局限性在于,如果其中一种模式不匹配,则将其传递给命令。在脚本中,当您要匹配目录中除.
和以外的所有文件时..
,有几种解决方案,它们都很麻烦:
使用* .*
枚举所有条目,并排除.
并..
在一个循环。一个或两个模式可能都不匹配,因此循环需要检查每个文件的存在。您有机会根据其他条件进行过滤;例如,-h
如果要跳过悬挂的符号链接,请删除测试。
for x in * .*; do
case $x in .|..) continue;; esac
[ -e "$x" ] || [ -h "$x" ] || continue
somecommand "$x"
done
一个更复杂的变体,其中命令仅运行一次。请注意,位置参数是很麻烦的(POSIX外壳没有数组)。如果存在问题,请将其放在单独的函数中。
set --
for x in * .[!.]* ..?*; do
case $x in .|..) continue;; esac
[ -e "$x" ] || [ -h "$x" ] || continue
set -- "$@" "$x"
done
somecommand "$@"
使用* .[!.]* ..?*
三联画。同样,一个或多个模式可能不匹配,因此我们需要检查现有文件(包括悬挂的符号链接)。
for x in * .[!.]* ..?*; do
[ -e "$x" ] || [ -h "$x" ] || continue
somecommand "$x"
done
使用* .[!.]* ..?*
tryptich,然后对每个模式运行一次命令,但前提是它匹配某些内容。这只会运行一次命令。请注意,位置参数很麻烦(POSIX外壳没有数组),如果存在问题,请将其放在单独的函数中。
set -- *
[ -e "$1" ] || [ -h "$1" ] || shift
set -- .[!.]* "$@"
[ -e "$1" ] || [ -h "$1" ] || shift
set -- ..?* "$@"
[ -e "$1" ] || [ -h "$1" ] || shift
somecommand "$@"
使用find
。使用GNU或BSD find,使用选项-mindepth
和可以轻松避免递归-maxdepth
。使用POSIX find,这有点棘手,但是可以做到。这种形式的优点是可以轻松地允许一次运行该命令,而不是每个文件一次(但不能保证:如果生成的命令太长,则该命令将分批运行)。
find . -name . -o -exec somecommand {} + -o -type d -prune
如果所有文件名均包含至少三个字符(包括点),则此方法有效:
chown -R root .??*
要获得更强大的解决方案,可以使用find
:
find . -maxdepth 1 -name '.*' -exec chown -R root {} \;