Linux 命令行:全局混淆

Jac*_* J. 5 command-line wildcards

我正在尝试了解 linux、它的命令行和这句话:

您可能会遇到 glob 问题,因为.*匹配...(当前和父目录)。您可能希望使用诸如.[^.]*或 之类的模式 .??*来获取除当前目录和父目录之外的所有点文件。

什么时候(在什么命令中)你会使用.[^.]*.??*

Sté*_*las 9

这是为了解决除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)。

作为历史记录,以.隐藏文件开头的文件名是由于某人试图跳过...首先出现的编码错误而产生的。具有讽刺意味的是,当我们尝试处理隐藏文件时,我们会遇到同样的问题。


Kus*_*nda 5

当您想将所有带有隐藏名称(以点开头)的文件和目录移动到另一个位置时:

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)

根据我的经验,想要在一个目录中做一些全点文件或点目录的事情很少发生。

  • 但是`.[^.]*` 会遗漏名为`..foo` 的文件。奇怪的是,像这样的负面模式直到今天仍然令人痛苦。 (2认同)