Ern*_*t A 14 shell filenames wildcards dot-files
最近我遇到了一个小事故,这是由一个以意想不到的方式扩展的贝壳图案造成的。我想更改/root目录中一堆点文件的所有者,所以我做了
chown -R root .*
Run Code Online (Sandbox Code Playgroud)
自然,.*扩大到..这有点灾难。
我知道bash可以通过调整一些 shell 选项来改变这种行为,但是在默认设置下,是否有任何模式可以扩展到目录中的每个点文件,但不能扩展到.和..?
Gil*_*il' 20
Bash、ksh 和 zsh 有更好的解决方案,但在这个答案中我假设一个 POSIX shell。
该模式.[!.]*匹配所有以点开头后跟非点字符的文件。(请注意,[^.]某些 shell 支持但不是全部,通配符模式中字符集补码的可移植语法是[!.]。)因此它不包括.和..,但也不包括以两个点开头的文件。该模式..?*处理以两个点开头的文件,而不仅仅是...
chown -R root .[!.]* ..?*
Run Code Online (Sandbox Code Playgroud)
这是匹配所有文件的经典模式集:
* .[!.]* ..?*
Run Code Online (Sandbox Code Playgroud)
这种方法的一个限制是,如果其中一个模式不匹配,则将其传递给命令。在脚本中,当你想匹配目录中除.and之外的所有文件时..,有几种解决方案,它们都很麻烦:
使用* .*枚举所有条目,并排除.并..在一个循环。一个或两个模式可能不匹配,因此循环需要检查每个文件是否存在。您有机会根据其他条件进行筛选;例如,-h如果您想跳过悬空的符号链接,请删除测试。
for x in * .*; do
case $x in .|..) continue;; esac
[ -e "$x" ] || [ -h "$x" ] || continue
somecommand "$x"
done
Run Code Online (Sandbox Code Playgroud)一个更复杂的变体,其中命令只运行一次。请注意,位置参数被破坏(POSIX shell 没有数组);如果这是一个问题,请将其放在一个单独的函数中。
set --
for x in * .[!.]* ..?*; do
case $x in .|..) continue;; esac
[ -e "$x" ] || [ -h "$x" ] || continue
set -- "$@" "$x"
done
somecommand "$@"
Run Code Online (Sandbox Code Playgroud)使用* .[!.]* ..?*三联画。同样,一个或多个模式可能不匹配,因此我们需要检查现有文件(包括悬空的符号链接)。
for x in * .[!.]* ..?*; do
[ -e "$x" ] || [ -h "$x" ] || continue
somecommand "$x"
done
Run Code Online (Sandbox Code Playgroud)使用* .[!.]* ..?*tryptich,并为每个模式运行一次命令,但前提是它匹配某些内容。这只会运行命令一次。请注意,位置参数被破坏(POSIX shell 没有数组),如果这是一个问题,请将其放在单独的函数中。
set -- *
[ -e "$1" ] || [ -h "$1" ] || shift
set -- .[!.]* "$@"
[ -e "$1" ] || [ -h "$1" ] || shift
set -- ..?* "$@"
[ -e "$1" ] || [ -h "$1" ] || shift
somecommand "$@"
Run Code Online (Sandbox Code Playgroud)使用find. 使用 GNU 或 BSD find,使用选项-mindepth和-maxdepth. 使用 POSIX find,它有点棘手,但可以完成。这种形式的优点是可以轻松地允许将命令运行一次,而不是每个文件一次(但这不能保证:如果生成的命令太长,命令将分几批运行)。
find . -name . -o -exec somecommand {} + -o -type d -prune
Run Code Online (Sandbox Code Playgroud)小智 6
如果所有文件名都包含至少三个字符(包括点),则此方法有效:
chown -R root .??*
Run Code Online (Sandbox Code Playgroud)
要获得更强大的解决方案,您可以使用find:
find . -maxdepth 1 -name '.*' -exec chown -R root {} \;
Run Code Online (Sandbox Code Playgroud)