文件夹

本页面讨论 Cloud Storage 中的文件夹,以及这些文件夹在 Cloud Storage 工具之间有何不同。

概览

Cloud Storage 使用平面命名空间运行,这意味着文件夹实际上不会存在于 Cloud Storage 中。如果您在存储桶 your-bucket 中创建名为 folder1/file.txt 的对象,则该对象的路径为 your-bucket/folder1/file.txt,但没有名为 folder1 的文件夹;字符串 folder1 是对象名称的一部分。

但是,Cloud Console 和 gsutil 可以提供分层文件树的幻觉:

  • Cloud Console 会以类似于本地文件浏览器的文件夹创建可视化的表示形式。

  • gsutil 使用各种规则模拟典型的命令行目录体验。

/storage/images/folders.svg

如果您使用 Cloud Console 创建空文件夹,则 Cloud Storage 会创建一个零字节对象作为占位符。例如,如果您在名为 my-bucket 的存储分区中创建名为 folder 的文件夹,系统会创建名为 gs://my-bucket/folder/ 的零字节对象。 您可以在运行 gsutil ls 时找到此对象。

工具

点击下面的标签,了解各个工具如何处理文件夹。

控制台

在 Cloud Console 中,您可以在存储分区中创建一个空文件夹,或上传现有文件夹。

当您上传现有文件夹时,该文件夹的名称将成为文件夹中所有对象的路径的一部分。所有子文件夹及其包含的对象也会包含在上传内容中。

要创建文件夹,请执行以下操作:

  1. 在 Google Cloud Console 中,转到 Cloud Storage 浏览器页面。

    转到浏览器

  2. 导航到存储分区。

  3. 点击创建文件夹以创建空的新文件夹,或点击上传文件夹来上传现有文件夹。

gsutil

为了实现错开分层文件树的视觉效果,gsutil 会应用以下规则来确定应将命令中的目标网址视为对象名称还是文件夹:

  1. 如果目标网址以 / 字符结尾,则 gsutil 会将目标网址视为文件夹。例如,假设存在以下命令,其中 your-file 是文件的名称:

    gsutil cp your-file gs://your-bucket/abc/

    其结果为,gsutil 会创建一个名为 gs://your-bucket/abc/your-file 的对象。

  2. 如果您将多个源文件复制到目标网址,则 gsutil 会将目标网址视为文件夹。例如,假设存在以下命令,其中 your-dir 是包含 file1file2 等文件的文件夹:

    gsutil cp -r your-dir gs://your-bucket/abc

    其结果为,gsutil 会创建对象 gs://your-bucket/abc/your-dir/file1gs://your-bucket/abc/your-dir/file2

  3. 如果上述规则均不适用,gsutil 会检查存储分区中的对象,以确定目标网址是对象名称还是文件夹。例如,假设存在以下命令,其中 your-file 是文件的名称:

    gsutil cp your-file gs://your-bucket/abc

    gsutil 会使用 / 分隔符和前缀=abc 针对 your-bucket 发出对象列出请求,以确定存储分区中是否有路径以 gs://your-bucket/abc/ 开头的对象。如果有,gsutil 会将 gs://your-bucket/abc 视为文件夹名称,并且上述命令会创建对象 gs://your-bucket/abc/your-file。否则,gsutil 会创建对象 gs://your-bucket/abc

gsutil 基于规则的方法与许多工具的工作方式不同,后者会创建 0 字节对象来标记文件夹的存在。gsutil 可理解此类工具使用的多种惯例,例如添加 _$folder$ 到 0 字节对象名称末尾的惯例,但 gsutil 不需要此类标记对象来实现与 UNIX 命令一致的命名行为。

重试和命名

如果您通过 gsutil 启用自动重试功能,则可能会遇到以下问题:第一次尝试仅会复制部分文件,而后续尝试则会遇到已有的目标文件夹,并且没有正确命名对象。

例如,假设存在以下命令,其中 your-dir/ 下存在子文件夹(如 dir1dir2),这两个子文件夹都包含文件 abc

gsutil cp -r ./your-dir gs://your-bucket/new

如果 gs://your-bucket/new 尚不存在,gsutil 会在第一次尝试成功时创建以下对象:

gs://your-bucket/new/dir1/abc
gs://your-bucket/new/dir2/abc

在下一次尝试成功时,gsutil 会创建以下对象:

gs://your-bucket/new/your-dir/dir1/abc
gs://your-bucket/new/your-dir/dir2/abc

如需让 gsutil 在每次尝试时都保持一致性,请尝试以下操作:

  1. 在目标网址的末尾添加斜杠,以便 gsutil 始终将其视为文件夹。

  2. 使用gsutil rsync。由于 rsync 不使用 Unix cp 定义的文件夹命名规则,因此无论目标子文件夹是否存在,它都会以一致的方式运行。

  3. 如果 gsutil rsync 不起作用,请创建占位符对象,以确定目标位置是文件夹。例如:

    gsutil cp some-file gs://your-bucket/new/placeholder

    在存在该占位符对象的情况下,运行以上 gsutil cp -r 命令会始终将 gs://your-bucket/new 视为文件夹。当您在 gs://your-bucket/new 下至少有一个对象后,可以删除该占位符对象并继续上传。

如需详细了解构建名称的方式,请参阅 gsutil help cp

补充说明

  • 您无法使用 gsutil 创建零字节对象来模拟空文件夹。

  • 如果您使用脚本通过组合子路径来构建文件路径,请注意,由于 / 只是位于对象名称中的字符,因此 gsutil 将 gs://my-bucket/folder/ 解释为与 gs://my-bucket//folder 不同的对象。

价格注意事项

gsutil 命名方法的一个缺点是,在执行 cpmv 命令(例如将文件夹以递归方式复制到云端)之前,它需要额外的对象列表。不过,这些列表的成本相对较低,因为它们使用分隔符和前缀参数来限制结果数据。此外,gsutil 仅针对每个 cpmv 命令发出一个对象列表请求,从而在所有传输的对象中分摊费用。

REST API

JSON API

JSON API 中不存在文件夹,但您可以使用prefixdelimiter 查询参数缩小列出的对象

例如,如需列出存储分区 my-bucket 中前缀为 folder/subfolder/ 的所有对象,请使用以下网址发出对象列出请求:

"https://storage.googleapis.com/storage/v1/b/my-bucket/o?prefix=folder/subfolder/"

XML API

XML API 中不存在文件夹,但您可以使用prefixdelimiter查询参数缩小搜索范围列出的对象

例如,如需列出存储分区 my-bucket 中前缀为 folder/subfolder/ 的所有对象,请使用以下网址发出对象列出请求:

"https://storage.googleapis.com/my-bucket?prefix=folder/subfolder/"