重命名和移动文件夹

本页介绍了如何在启用了分层命名空间的存储桶中重命名和移动文件夹。

重命名操作会在单个原子操作中以递归方式重命名文件夹、其子文件夹以及关联的资源(包括对象和托管式文件夹)。

重命名操作是原子操作。操作要么成功完成并将资源移至新路径,要么失败并显示错误。如果发生错误,所有资源都会恢复为原始状态。

在启用了分层命名空间的存储桶中,重命名文件夹只是一项仅涉及元数据的操作。它不涉及物理移动或复制文件夹中的对象,因此不会产生对象复制费用。

不过,在未启用分层命名空间的存储桶中,系统会模拟文件夹。若要重命名或移动模拟文件夹,则需要复制并删除其中的每个对象。如果文件夹包含许多对象,重命名过程可能会效率低下且成本高昂。重命名或移动模拟文件夹也是非原子操作,这意味着,如果该过程失败,存储桶可能会处于不一致状态,并且只有部分对象会被移动。

在重命名文件夹的过程中,您可以读取和列出要重命名的资源。不过,您无法对受影响的资源运行写入操作。

文件夹重命名操作会对存储桶启动长时间运行的操作

所需的角色

如需获得在存储桶中重命名或移动文件夹所需的权限,请让您的管理员为您授予存储桶的 Storage Object User (roles/storage.objectUser) IAM 角色。

如需详细了解如何授予项目的角色,请参阅管理对项目的访问权限

如需查看所需的确切权限,请展开所需权限部分:

所需权限

  • storage.folders.rename
    • 源文件夹需要此权限。
  • storage.folders.create
    • 目标文件夹需要此权限。

您也可以使用其他自定义角色预定义角色来获取上述权限。如果您需要更宽松的角色,除了重命名文件夹之外还可以管理文件夹,请让您的管理员为您授予以下角色之一:

  • Storage Folder Admin (roles/storage.folderAdmin)
  • Storage Object Admin (roles/storage.objectAdmin)
  • Storage Admin (roles/storage.admin)

如需查看哪些角色与哪些权限相关联,请参阅适用于 Cloud Storage 的 IAM 角色

重命名和移动文件夹

控制台

  1. 在 Google Cloud 控制台中,进入 Cloud Storage 存储桶页面。

    进入“存储桶”

  2. 在存储桶列表中,点击包含您要移动或重命名的文件夹的存储桶的名称。

  3. 存储分区详情页面中,找到要移动或重命名的文件夹。

  4. 如果您要重命名文件夹,请执行以下操作:

    1. 点击相应文件夹的 更多操作菜单。

    2. 点击重命名文件夹

    3. 在出现的叠加窗口中,输入文件夹的新名称。

    4. 点击重命名

  5. 如果您要将该文件夹移至其他文件夹,请执行以下操作:

    1. 点击相应文件夹的 更多操作菜单。

    2. 点击移动文件夹

    3. 在出现的叠加窗口中,点击浏览

    4. 选择您要移动的文件夹的目标文件夹。您也可以点击 创建新文件夹,然后选择其作为目标文件夹。

    5. 点击选择

    6. 点击移动

如需了解如何在 Google Cloud 控制台中获取失败的 Cloud Storage 操作的详细错误信息,请参阅问题排查

命令行

如需重命名或移动使用分层命名空间的存储桶中的文件夹,请运行 gcloud storage mv 命令:

gcloud storage mv gs://BUCKET_NAME/FOLDER1 gs://BUCKET_NAME/FOLDER2

其中:

  • BUCKET_NAME 是包含您要重命名或移动的文件夹的存储桶的名称。例如 my-bucket
  • FOLDER1 是您要重命名或移动的原始文件夹的名称。例如 my-src-folder
  • FOLDER2 是目标文件夹的新名称。例如 my-dest-folder。如果您选择的新名称已被现有文件夹使用,原始文件夹会移至现有文件夹中,成为子文件夹。例如,如果您将 my-dest-folder 重命名为 my-dest-folder1(并且 my-dest-folder1 已存在),则结果为 my-dest-folder1/my-dest-folder/。如果您选择的新名称尚不存在,原始文件夹会重命名以与新名称匹配。

响应如下例所示:

Copying gs://my-bucket/my-src-folder to gs://hns-bucket/my-dest-folder...

客户端库

C++

如需了解详情,请参阅 Cloud Storage C++ API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

namespace storagecontrol = google::cloud::storagecontrol_v2;
[](storagecontrol::StorageControlClient client,
   std::string const& bucket_name, std::string const& source_folder_id,
   std::string const& dest_folder_id) {
  auto name = std::string{"projects/_/buckets/"} + bucket_name + "/folders/" +
              source_folder_id;
  // Start a rename operation and block until it completes. Real applications
  // may want to setup a callback, wait on a coroutine, or poll until it
  // completes.
  auto renamed = client.RenameFolder(name, dest_folder_id).get();
  if (!renamed) throw std::move(renamed).status();

  std::cout << "Renamed: " << source_folder_id << " to: " << dest_folder_id
            << "\n";
}

C#

如需了解详情,请参阅 Cloud Storage C# API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

using Google.Cloud.Storage.Control.V2;
using System;

public class StorageControlRenameFolderSample
{
    public Folder StorageControlRenameFolder(string bucketName = "your-unique-bucket-name",
        string sourceFolderName = "your_folder_name", string targetFolderName = "target_folder_name")
    {
        StorageControlClient storageControl = StorageControlClient.Create();

        string folderResourceName =
            // Set project to "_" to signify globally scoped bucket
            FolderName.FormatProjectBucketFolder("_", bucketName, sourceFolderName);

        var operation = storageControl.RenameFolder(folderResourceName, targetFolderName);
        var folder = operation.PollUntilCompleted().Result;

        Console.WriteLine($"Renamed folder {sourceFolderName} to {targetFolderName}");
        return folder;
    }
}

Go

如需了解详情,请参阅 Cloud Storage Go API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

import (
	"context"
	"fmt"
	"io"
	"time"

	control "cloud.google.com/go/storage/control/apiv2"
	"cloud.google.com/go/storage/control/apiv2/controlpb"
)

// renameFolder changes the name of an existing folder.
func renameFolder(w io.Writer, bucket, src, dst string) error {
	// bucket := "bucket-name"
	// src := "original-folder-name"
	// dst := "new-folder-name"

	ctx := context.Background()
	client, err := control.NewStorageControlClient(ctx)
	if err != nil {
		return fmt.Errorf("NewStorageControlClient: %w", err)
	}
	defer client.Close()

	ctx, cancel := context.WithTimeout(ctx, time.Second*30)
	defer cancel()

	// Construct source folder path including the bucket name.
	srcPath := fmt.Sprintf("projects/_/buckets/%v/folders/%v", bucket, src)

	req := &controlpb.RenameFolderRequest{
		Name:                srcPath,
		DestinationFolderId: dst,
	}
	op, err := client.RenameFolder(ctx, req)
	if err != nil {
		return fmt.Errorf("RenameFolder(%q): %w", srcPath, err)
	}

	// Wait for long-running operation to complete.
	f, err := op.Wait(ctx)
	if err != nil {
		return fmt.Errorf("waiting for RenameFolder: %w", err)
	}

	fmt.Fprintf(w, "folder %v moved to new path %v", srcPath, f.Name)
	return nil
}

Java

如需了解详情,请参阅 Cloud Storage Java API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证


import com.google.api.gax.longrunning.OperationFuture;
import com.google.storage.control.v2.Folder;
import com.google.storage.control.v2.FolderName;
import com.google.storage.control.v2.RenameFolderMetadata;
import com.google.storage.control.v2.RenameFolderRequest;
import com.google.storage.control.v2.StorageControlClient;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public final class RenameFolder {

  public static void renameFolder(
      String bucketName, String sourceFolderName, String destinationFolderName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // The name of the bucket
    // String bucketName = "your-unique-bucket-name";

    // The name of the folder within the bucket
    // String sourceFolderName = "your-unique-source-folder-name";

    // The new name of the folder within the bucket
    // String destinationFolderName = "your-unique-destination-folder-name";

    try (StorageControlClient storageControl = StorageControlClient.create()) {

      // Set project to "_" to signify globally scoped bucket
      String sourceFolderResourceName = FolderName.format("_", bucketName, sourceFolderName);
      RenameFolderRequest request =
          RenameFolderRequest.newBuilder()
              .setName(sourceFolderResourceName)
              .setDestinationFolderId(destinationFolderName)
              .build();

      OperationFuture<Folder, RenameFolderMetadata> renameOperation =
          storageControl.renameFolderAsync(request);

      Folder destinationFolder = renameOperation.get(30, TimeUnit.SECONDS);

      System.out.printf(
          "Renamed folder from %s to %s%n", sourceFolderResourceName, destinationFolder.getName());
    }
  }
}

Node.js

如需了解详情,请参阅 Cloud Storage Node.js API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */

// The name of your GCS bucket
// const bucketName = 'bucketName';

// The source folder name
// const sourceFolderName = 'currentFolderName';

// The destination folder ID
// const destinationFolderName = 'destinationFolderName';

// Imports the Control library
const {StorageControlClient} = require('@google-cloud/storage-control').v2;

// Instantiates a client
const controlClient = new StorageControlClient();

async function callRenameFolder() {
  const folderPath = controlClient.folderPath(
    '_',
    bucketName,
    sourceFolderName
  );

  // Create the request
  const request = {
    name: folderPath,
    destinationFolderId: destinationFolderName,
  };

  // Run request
  await controlClient.renameFolder(request);
  console.log(
    `Renamed folder ${sourceFolderName} to ${destinationFolderName}.`
  );
}

callRenameFolder();

PHP

如需了解详情,请参阅 Cloud Storage PHP API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

use Google\Cloud\Storage\Control\V2\Client\StorageControlClient;
use Google\Cloud\Storage\Control\V2\RenameFolderRequest;

/**
 * Rename a folder in an existing bucket.
 *
 * @param string $bucketName The name of your Cloud Storage bucket.
 *        (e.g. 'my-bucket')
 * @param string $sourceFolder The source folder ID.
 *        (e.g. 'my-folder')
 * @param string $destinationFolder The destination folder ID.
 *        (e.g. 'my-folder')
 */
function rename_folder(string $bucketName, string $sourceFolder, string $destinationFolder): void
{
    $storageControlClient = new StorageControlClient();

    // Set project to "_" to signify global bucket
    $formattedName = $storageControlClient->folderName('_', $bucketName, $sourceFolder);

    $request = new RenameFolderRequest([
        'name' => $formattedName,
        'destination_folder_id' => $destinationFolder,
    ]);

    $storageControlClient->renameFolder($request);

    printf('Renamed folder %s to %s', $sourceFolder, $destinationFolder);
}

Python

如需了解详情,请参阅 Cloud Storage Python API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

from google.cloud import storage_control_v2


def rename_folder(
    bucket_name: str, source_folder_name: str, destination_folder_name: str
) -> None:
    # The ID of your GCS bucket
    # bucket_name = "your-unique-bucket-name"
    #
    # The source folder ID
    # source_folder_name = "current-folder-name"
    #
    # The destination folder ID
    # destination_folder_name = "new-folder-name"

    storage_control_client = storage_control_v2.StorageControlClient()
    # The storage bucket path uses the global access pattern, in which the "_"
    # denotes this bucket exists in the global namespace.
    source_folder_path = storage_control_client.folder_path(
        project="_", bucket=bucket_name, folder=source_folder_name
    )

    request = storage_control_v2.RenameFolderRequest(
        name=source_folder_path,
        destination_folder_id=destination_folder_name,
    )

    operation = storage_control_client.rename_folder(request=request)
    operation.result(60)

    print(f"Renamed folder {source_folder_name} to {destination_folder_name}")

Ruby

如需了解详情,请参阅 Cloud Storage Ruby API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

def rename_folder bucket_name:, source_folder_id:, destination_folder_id:
  # The ID of your GCS bucket
  # bucket_name = "your-unique-bucket-name"
  #
  # The source folder ID
  # source_folder_id = "current-folder-id"
  #
  # The destination folder ID, e.g. foo/bar/
  # destination_folder_id = "destination-folder-id"

  require "google/cloud/storage/control"

  storage_control = Google::Cloud::Storage::Control.storage_control

  # The storage folder path uses the global access pattern, in which the "_"
  # denotes this bucket exists in the global namespace.
  folder_path = storage_control.folder_path project: "_", bucket: bucket_name, folder: source_folder_id

  request = Google::Cloud::Storage::Control::V2::RenameFolderRequest.new name: folder_path,
                                                                         destination_folder_id: destination_folder_id

  storage_control.rename_folder request

  puts "Renamed folder #{source_folder_id} to #{destination_folder_id}"
end

REST API

JSON API

  1. 安装并初始化 gcloud CLI,以便为 Authorization 标头生成访问令牌。

  2. 使用 cURL 通过重命名文件夹的请求调用 JSON API

    curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/folders/SOURCE_PATH/renameTo/folders/DESTINATION_PATH"

    其中:

    • BUCKET_NAME 是包含您要重命名或移动的文件夹的存储桶的名称。例如 my-bucket
    • SOURCE_PATH 是源文件夹的网址编码路径。例如,my-src-folder/ 的网址编码为 my-src-folder%2F
    • DESTINATION_PATH 是目标文件夹的网址编码路径。例如,my-dest-folder/ 的网址编码为 my-dest-folder%2F

后续步骤

自行试用

如果您是 Google Cloud 新手,请创建一个账号来评估 Cloud Storage 在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。

免费试用 Cloud Storage