通配符名称

说明

gsutil 支持适用于文件、存储桶和对象的 URI 通配符。例如,以下命令:

gsutil cp gs://bucket/data/abc* .

将复制该子目录中的所有以下对象:以 gs://bucket/data/abc 开头,后跟任意数量的字符。

通配符字符

gsutil 使用以下通配符:

*
匹配当前目录级别中的任意数量的字符。例如,gs://my-bucket/abc/d* 与对象 abc/def.txt 匹配,但与 abc/def/g.txt 对象不匹配。
**
匹配目录边界内任意数量的字符。用作本地文件路径的一部分时,** 通配符应始终以目录分隔符开头。例如,my-directory/**.txt 有效,但 my-directory/abc** 无效。
匹配单个字符。例如,gs://bucket/??.txt 仅匹配两个字符后跟 .txt 的对象。
[字符]
匹配任何指定字符。例如,gs://bucket/[aeiou].txt 与包含单个元字符(后跟 .txt)的对象匹配。
[字符范围]
匹配任何字符范围。例如,gs://bucket/[a-m].txt 匹配包含字母 a、b、c、...或 m 并以 .txt 结尾的对象。

您可以组合通配符来提供更强大的匹配功能,例如:

gs://*/[a-m]??.j*g

请注意,除非您的命令包含在结果中返回非当前对象版本的标志,否则这些通配符只能与活动对象版本匹配。

gsutil 支持对象和文件名使用相同的通配符。因此,例如:

gsutil cp data/abc* gs://bucket

匹配本地文件系统的 data 目录中以 abc 开头的所有文件。

使用通配符时可能会出现的意外行为

有些使用通配符的方法可能会导致意外行为:

  1. 在存储桶名称中使用通配符时,匹配项仅限于 -p 标志中指定的项目中的存储桶。某些命令(例如 gsutil rm)不支持 -p 标志。如果 -p 标志未用于命令,或者无法使用命令,则匹配项仅限于默认项目中的存储桶。

  2. Shell(如 bash 和 zsh)会尝试在将参数传递给 gsutil 之前扩展通配符。如果通配符应该引用云端对象,则可能会导致意外的“未找到”错误(例如,如果 shell 尝试在本地计算机上扩展通配符 gs://my-bucket/*,则不匹配任何本地文件,且命令失败)。

    请注意,一些 shell 的通配符字符集中包含其他字符。例如,如果您在启用 extendedglob 选项的情况下使用 zsh,则系统会将 # 视为特殊字符,因为该字符在引用有版本控制的对象时会使用该字符并造成冲突(请参阅恢复非当前对象版本获取示例)。

    为避免这些问题,请使用英文单引号(Linux 上)或英文双引号(Windows 上)括住通配符表达式。

  3. 尝试指定包含通配符的文件名时操作无效,这是因为 gsutil 将试着扩展通配符,而不是以字面量字符的形式使用通配符。例如,运行命令:

    gsutil cp './file[1]' gs://my-bucket
    

    会导致 gsutil 尝试将 [1] 部分作为通配符进行匹配。

    支持 gsutil 以“原始”模式提供方法处理包含通配符的文件名时,会出现一个公认的问题,直到/除非该支持得到实现,否则使用 gsutil 处理此类文件名没有真正好的方法。您可以使用通配符来命名此类文件,例如将上述命令替换为:

    gsutil cp './file*1*' gs://my-bucket
    

    但这种方法一般可能不好用。

本地文件系统中“Dot”文件的不同行为

根据标准的 Unix 行为,通配符 * 仅匹配不以 . 字符开头的文件(为了避免与所有 Unix 目录中展示的 ... 目录存相混淆)。通过文件系统 URI 使用通配符时,gsutil 可提供相同的行为,但不通过 Cloud URI 提供此行为。例如,以下命令会将 gs://bucket1 中的所有对象复制到 gs://bucket2:

gsutil cp gs://bucket1/* gs://bucket2

但是,以下命令只会将不以 . 开头的文件从目录 dir 复制到 gs://bucket1:

gsutil cp dir/* gs://bucket1

效率注意事项:针对多个对象使用通配符

下面两种方法相比,前者更高效、快速,且密集型网络流量更少:使用具有非通配符对象名称前缀的通配符,例如:

gs://bucket/abc*.txt

与将通配符用作对象名称的第一部分相比,例如:

gs://bucket/*abc.txt

这是因为 gs://bucket/abc*.txt 请求要求服务器发送回存储分区根目录中对象名称以 abc 开头的结果的子集,然后 gsutil 过滤结果列表以得到名称以 .txt 结尾的对象。相比之下,gs://bucket/*abc.txt 要求服务器提供存储分区根目录中对象的完整列表,然后过滤获取名称以 abc.txt 结尾的对象。当您使用包含数千个或更多对象的存储分区时,这种效率考量会愈加明显。有时,您可以设置对象的名称,使其符合预期的通配符匹配模式,从而利用进行服务器端前缀请求的效率。如需查看示例用例,请参阅相关文档,例如 gsutil 帮助:生产

效率注意事项:使用路径中间通配符

假设您有一个包含以下对象的存储分区:

gs://bucket/obj1
gs://bucket/obj2
gs://bucket/obj3
gs://bucket/obj4
gs://bucket/dir1/obj5
gs://bucket/dir2/obj6

如果您运行以下命令:

gsutil ls gs://bucket/*/obj5

gsutil 会执行 / 分隔的顶层存储分区列出,然后针对每个子目录执行一次存储分区列出,总共 3 次存储分区列出:

GET /bucket/?delimiter=/
GET /bucket/?prefix=dir1/obj5&delimiter=/
GET /bucket/?prefix=dir2/obj5&delimiter=/

通配符要求的存储分区列出越多,其速度越慢,费用也就越高。所需存储分区列出的次数会随下列因素增加:

  • 通配符元素的数量(例如 “gs://bucket/a??b/c*/*/d”中包含 3 个通配符元素);
  • 与每个元素匹配的子目录的数量;以及
  • 结果的数量(每 1000 个结果使用一次 GET 请求实现一次分页,从而为每页指定标记)。

如果要使用路径中间通配符,您可以尝试改用递归通配符,例如:

gsutil ls gs://bucket/**/obj5

它匹配的对象将比 gs://bucket/*/obj5(因为它跨目录)更多,但会使用分隔符更少的存储分区列出请求(这意味着存储分区请求减少,但它会列出整个存储分区并进行本地过滤,因此可能需要大量的网络流量。)