Jac*_* J. 5 command-line wildcards
我正在尝试了解 linux、它的命令行和这句话:
您可能会遇到 glob 问题,因为
.*
匹配.
和..
(当前和父目录)。您可能希望使用诸如.[^.]*
或 之类的模式.??*
来获取除当前目录和父目录之外的所有点文件。
什么时候(在什么命令中)你会使用.[^.]*
或.??*
?
这是为了解决除zsh
,fish
以及 Forsyth shell 的后代(包括pdksh
和衍生物)之外的 shell 中的错误/错误功能,其中.*
globs 包括.
和..
(在系统上(大多数,不幸的是)readdir()
返回它们的系统)
有了这些贝壳,
chmod -R og-rwx .*
Run Code Online (Sandbox Code Playgroud)
例如,将递归删除当前目录和父目录的 rwx 权限,而不仅仅是当前目录中的隐藏文件和目录。必须为此添加一个变通方法rm
,因为太多人绊倒了rm -rf .*
。
它也(可能更频繁地)用于将所有文件(隐藏或不隐藏)作为参数传递给命令 ( cmd .[!.]* ..?* *
),您会根据 shell 找到其他解决方法。
这是特别糟糕的是做事递归或类似目录的行动命令ls .*
,chown -R .*
,find .*
,grep -r blah .*
但它仍然是烦人的大多数其他命令,我想不出你会希望有那些任何命令.
,并..
包含在文件列表传给他们。
该.[^.]*
水珠(.[!.]*
布赫纳/ POSIX壳)排除.
(因为它与至少两个字符的文件名上匹配)和..
(作为第二个字符是.
不匹配[^.]
),但也排除了文件,如..foo
,在您需要的第二水珠..?*
。
那些.
和..
用于遍历目录的工具,这是他们应该像普通文件中列出的一个错误。POSIX 要求它们在路径组件(如 in open(".")
, stat("foo/../bar")
)中被理解,但不一定作为目录条目实现,也不必包含在readdir()
.
尽管如此,大多数系统仍然将早期 Unices 中的那些实现为硬链接,而那些没有实现的系统仍然会在getdents()
/的输出中为它们伪造条目readdir()
。
使用bash
,另一种方法是打开该dotglob
选项并使用:
chmod -R og-rwx [.]*
Run Code Online (Sandbox Code Playgroud)
(但请注意,如果没有非隐藏文件,它可能会更改[.]*
文件的权限,除非您failglob
可以选择模仿zsh
/的行为fish
)。
作为历史记录,以.
隐藏文件开头的文件名是由于某人试图跳过.
而..
首先出现的编码错误而产生的。具有讽刺意味的是,当我们尝试处理隐藏文件时,我们会遇到同样的问题。
当您想将所有带有隐藏名称(以点开头)的文件和目录移动到另一个位置时:
mv .[^.]* old-dot-files/
Run Code Online (Sandbox Code Playgroud)
或者,每当您想对目录中的所有点文件或点目录执行任何操作时:
for name in .[^.]*; do
# process "$name"
done
Run Code Online (Sandbox Code Playgroud)
请注意,该模式.??*
要求匹配的名称至少包含三个字符,因此.a
不会选取类似名称。 .[^.]*
另一方面,将跳过名称开头带有双点的任何内容。
显式测试匹配的名称可能会更好:
for name in .*; do
# expecting a regular file
if [ -f "$name" ]; then
# process "$name"
fi
done
for name in .*; do
# expecting a directory other than . and ..
if [ -d "$name" ] && [ "$name" != '.' ] && [ "$name != '..' ]; then
# process "$name"
fi
done
Run Code Online (Sandbox Code Playgroud)
根据我的经验,想要在一个目录中做一些全点文件或点目录的事情很少发生。