到底什么时候你会使用“.[^.]*”或“.??*”全局模式?

到底什么时候你会使用“.[^.]*”或“.??*”全局模式?

我试图理解 Linux、它的命令行和这句话:

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

您究竟何时(在什么命令中)使用.[^.]*or .??*

答案1

这是为了解决除zsh,fish以及 Forsyth shell 的后代(包括pdksh和 衍生物)之外的 shell 中的错误/错误功能,其中 glob 的扩展.*包括...(在系统上(不幸的是,在readdir()返回它们的系统上)

有了这些贝壳,

chmod -R og-rwx .*

例如,将递归地删除当前 ( .) 和父 ( ..) 目录的 rwx 权限,而不仅仅是当前目录中的隐藏文件和目录。

ls .*对于递归执行操作或作用于、chown -R .*、等目录的命令来说find .*,这尤其糟糕,grep -r blah .*但对于大多数其他命令来说,它仍然很烦人,而且我想不出任何您希望拥有这些命令...包含在文件列表中的命令传递给他们。

必须在rm实用程序中添加保障措施解决这个错误,因为太多人被绊倒了rm -rf .*

添加后*,它还用于将所有文件(隐藏或不隐藏)作为参数传递给命令 ( cmd -- .[!.]* ..?* *),其中根据 shell,您会找到其他解决方法

glob .[^.]*.[!.]*在 Bourne/POSIX shell 中)排除.(因为它匹配至少有两个字符的文件名) 和..(因为第二个字符是.不匹配的[^.]),但也排除像 之类的文件..foo,您需要第二个 glob ..?*

这些...是目录遍历的工具,将它们像普通文件一样列出是错误的。 POSIX 要求它们在路径组件中被理解(如在open("."),中stat("foo/../bar")),但不一定被实现为目录条目,也不一定包含在 中readdir()

尽管如此,大多数系统仍然像早期的 Unices 那样实现硬链接,并且大多数不这样做的系统仍然会在getdents()/的输出中为它们伪造条目readdir()

对于bash,另一种方法是打开该dotglob选项并使用:

chmod -R og-rwx [.]*

(但请注意,如果没有非隐藏文件,它可能会更改[.]*文件的权限,除非您可以选择模仿/failglob的行为)。zshfish

作为历史记录,以.隐藏文件开头的文件名是诞生于某人试图跳过的编码错误.,并且..首先。具有讽刺意味的是,当尝试使用隐藏文件执行操作时,我们会遇到同样的问题。


¹ 另请参阅globskipdotsbash 5.2+ 中的选项

答案2

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

mv .[^.]* old-dot-files/

或者,每当您想对目录中的所有点文件或点目录执行任何操作时:

for name in .[^.]*; do
   # process "$name"
done

请注意,该模式.??*要求匹配的名称至少包含三个字符,因此.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

根据我的经验,想要对目录中的所有点文件或点目录执行某些操作的情况很少发生。

相关内容