如果使用错误的 Linux 通配符,您将面临数据丢失的风险如果使用错误的 Linux 通配符,您将面临数据丢失的风险如果使用错误的 Linux 通配符,您将面临数据丢失的风险如果使用错误的 Linux 通配符,您将面临数据丢失的风险
  • 业务
  • 目标
  • 支持
  • 登录
找到的结果: {phrase} (显示: {results_count} 共: {results_count_total})
显示: {results_count} 共: {results_count_total}

加载更多搜索结果...

搜索范围
模糊匹配
搜索标题
搜索内容

如果使用错误的 Linux 通配符,您将面临数据丢失的风险

发表 admin at 2025年2月28日
类别
  • 未分类
标签

Linux 通配符使您可以键入同时作用于整组文件的单个命令。除非出现问题,否则这可以节省大量时间。他们可以。具有破坏性。

通配符的用途是什么

众所周知的通配符是问号 ? 和星号 *。这些可用于创建文件名模式。问号代表任何单个字符,星号代表任何字符序列,包括零个字符。

知道了这一点,我们就可以构造匹配多个文件名的模式。我们不是在命令行上输入所有文件名,而是输入模式。该命令将作用于与该模式匹配的所有文件。

如果我们在这样的目录中有一个文件集合:

我们可以选择与我们提供的模式匹配的文件组。

ls taf_* 

这为我们提供了名称开头带有“taf_”的所有文件。

ls *.sh
ls s*.sh

第一个命令列出目录中的所有 shell 脚本文件。第二个命令仅列出以“s”开头的文件,这些文件也是 shell 脚本文件。

这一切看起来都很简单,使用 ls 确实如此。但其他命令可以使用这种类型的模式匹配。当 shell 在命令有机会之前尝试通过模式匹配提供帮助时,就会出现问题。

将星号与 find 命令一起使用

将模式扩展为匹配文件列表的操作称为通配。

它最初是 Unix 版本 6 中的一个独立命令,然后成为一个可以链接到其他程序的库,现在它是一个内置的 shell。模式的扩展由 shell 执行,扩展的结果作为命令行参数传递给命令。

我们将看两个使用 find 命令的示例。第一种做法符合您的预期,但第二种做法可能会让您大吃一惊。

在本例中,我们将使用一个包含单个文件的目录,名为 readme.txt。有两个目录,src 和 inc。它们包含 C、H、MD 和 TMP 文件的混合。

ls -R

我们可以使用 find 递归地查找名称与我们的模式 (-name *.c) 匹配的文件 (-type f),从而为我们提供 C 文件的列表。

find . -type f -name *.c

我们可以添加 -not 选项来反转搜索,向我们显示除 C 文件之外的所有内容。

find . -type f -not -name *.c

查看此列表后,我们选择删除除 C 文件之外的所有内容。我们可以通过添加 -delete 选项来做到这一点。

find . -type f -not -name *.c -delete
find .

第二个 find 命令递归列出当前目录及其下的所有内容。剩下的就是我们的 C 文件。

这就像我们大多数人所期望的那样。现在我们将做完全相同的事情,但这次当前目录中的文件不是文本文件,而是 C 文件。

ls -R

我们将使用相同的 find 命令和选项来删除除 C 文件之外的所有内容。这根本不是我们想要的。

find . -type f -not -name *.c -delete
find .

除了当前目录中的一个 C 文件之外,目录树中的每个文件都被愉快地删除了。

我们将再次重置文件,并按照我们应该使用的方式发出命令。

所有文件都已就位,并且我们在当前目录中有一个 C 文件,就像我们之前所做的那样。

ls -R

这次,我们将通配符模式用单引号引起来。

find . -type f -not -name '*.c' -delete
find .

这就是我们想要的。除了我们的 C 文件之外,一切都消失了。

好的,那么出了什么问题呢?

单引号阻止 shell 扩展文件名模式。它按原样传递给命令或程序,以便命令执行操作。

在有效的示例中,我们在当前目录中有一个 readme.txt 文件。 shell 无法找到与 *.c 匹配的内容,因此它通过 *.c 来查找并执行操作。

在删除除 C 文件之外的所有内容的示例中,我们在当前目录中有一个名为 main.c 的文件。 shell 将模式与该文件进行匹配,并将文件名传递给 find 命令。所以 find 的指令是删除所有不叫 main.c 的东西。

我们可以用一个小型 C 程序来说明这一点,该程序仅在终端窗口中显示其命令行参数。

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) 
{
    int i;
    printf("You supplied %d arguments.\n", argc-1);
    for (i=1; i<argc; i++)
            printf("%-2d) \"%s\"\n", i, argv[i]);
    exit (0);
}

我将其保存为名为 glob.c 的文件,并使用以下命令进行编译:

gcc -o glob glob.c

变量 argc 保存我们传递给程序的参数数量。 for 循环遍历参数列表并将每个参数打印到终端窗口。

for 循环从参数 1 开始,而不是从零开始。有一个参数为零。它始终保存二进制文件本身的名称。为了避免混淆水,我避免打印它。唯一打印的参数是我们在命令行上提供的参数。

./glob one two 3 ant beetle cockroach

让我们尝试使用 *.c 作为命令行参数。

ls *.c
./glob *.c

当前目录中没有任何 C 文件,shell 会将 *.c 传递给 find 命令。然后 find 命令作用于通配符模式本身。但是,当当前目录中有一个 C 文件时,shell 会将匹配的 C 文件的名称传递给程序。

ls *.c
./glob *.c

我们的程序接收 C 文件的名称作为其参数,find 命令也是如此。所以实际上,find 正在执行它被告知执行的操作:删除除 main.c 文件之外的所有文件。

这次,我们将通配符模式用单引号引起来。

ls *.c

./glob '*.c'

shell 忽略将其通配符应用于通配符模式的机会,并将其直接传递给命令以进行进一步处理。

一个简单的修复,你可以引用我的话

作为一般规则,请引用传递给 find 等命令的通配符模式。这就是防止此类潜在灾难性事故所需的全部措施。

©2015-2025 Norria support@norria.com