从控制台与 CLI 创建时如何确保 S3 前缀相同?
How to ensure S3 prefixes are same when created from console vs CLI?
我想在 S3 中创建以下文件夹结构,
/demo/app/a.txt
通过控制台:
demo
和 app
使用“创建文件夹”,然后 a.txt
文件上传
通过 CLI:
aws s3 sync . s3://<my-bucket>/
,其中 .
(当前目录)有 demo
个文件夹
--
现在当我运行,
aws s3 ls s3://<my-bucket> --recursive
,结果相当interesting/puzzling!
输出:
# created & uploaded from console
demo/
demo/app/
demo/app/a.txt
# from CLI
demo/app/a.txt
显然,demo/
和 demo/app/
没有任何 prefixes/objects 使用 CLI 上传创建。
--
帮助我理解了当文件夹是空的。但是通过 CLI 上传时就不是这样了。
那么,如何模仿 CLI 上传的 0 字节 文件行为?也就是说,匹配前缀!
另一个用例是,由于前缀不可用,无法从浏览器浏览目录。例如
- 从控制台上传:
https://<domain>/demo/
显示 app
目录。
- 从 CLI 上传:
https://<domain>/demo/
结果为 NoSuchKeyError
--
注意:我正在使用 CloudFront
分发来访问 S3 数据(如果有帮助的话)!
Amazon S3 是一个平面对象存储系统。它不是文件系统,也没有文件夹或目录的概念。相反,对象的 Key
(文件名)包含对象的 完整路径 。
使用 S3 的最简单方法是假装文件夹存在,但实际上并不创建它们。例如,您可以像这样将文件复制到 S3:
aws s3 cp a.txt s3://my-bucket/demo/app/a.txt
这将成功运行,即使没有名为 demo
或 app
的目录,因为 directories/folders 不存在 .
相反,Amazon S3 提供了 CommonPrefix
的概念,您将在 ListObjects()
API 调用的底部看到它。此 returns 由 分隔符 (通常为 /
)分隔的类似文件夹的名称列表。这提供了目录的编程等效性,而不需要它们实际存在。
如果您希望呈现一系列分层目录,请使用 CommonPrefixes
的列表来构建该视图。即使没有零长度文件,这也会起作用,因为 S3 查看对象的键,而不是实际目录。
这里有一些例子:
aws s3 cp a.txt s3://my-bucket/demo/app/a.txt
upload: ./a.txt to s3://my-bucket/demo/app/a.txt
aws s3api list-objects-v2 --bucket my-bucket
{
"Contents": [
{
"Key": "demo/app/a.txt",
"LastModified": "2020-04-22T01:11:20+00:00",
"ETag": "\"802776735eb3ddcf03962ae47e08ed13\"",
"Size": 211,
"StorageClass": "STANDARD"
}
]
}
aws s3api list-objects-v2 --bucket my-bucket --delimiter '/'
{
"CommonPrefixes": [
{
"Prefix": "demo/"
}
]
}
aws s3api list-objects-v2 --bucket jstack-b --delimiter '/' --prefix 'demo/'
{
"CommonPrefixes": [
{
"Prefix": "demo/app/"
}
]
}
请注意末尾的命令如何提供 delimiter
,因此会返回 CommonPrefixes
的列表。您可以通过这种方式遍历目录列表(不存在)。
如果您确实需要在 S3 中存在一个反映本地文件夹结构的文件夹结构,那么您可以尝试以下 shell 脚本和 Linux 或 [=45 上的 awscli 的一些变体=]:
- 列出所有本地文件夹
- 将该列表转换为与 S3 命名约定匹配的内容
- 在 S3 中的每个文件夹名称处创建一个零字节文件
列出本地文件夹:
find . -type d
示例输出:
.
./dogs
./dogs/cute
./dogs/fierce
./cats
./cats/white
./cats/black
转换该列表以删除 .
,以便 ./dogs/cute
变为 dogs/cute
:
find . -type d | grep -v '^\.$' | sed 's/^\.\///g'
示例输出:
dogs
dogs/cute
dogs/fierce
cats
cats/white
cats/black
最后将它们放在一起并在每个文件夹中创建零字节文件:
find . -type d \
| grep -v '^\.$' \
| sed 's/^\.\///g' \
| xargs -L 1 -I % \
aws s3api put-object --bucket mybucket --key %/ --content-length 0
检查 S3 中的结果:
aws s3 ls s3://mybucket --recursive
结果:
2020-04-21 21:00:05 0 cats/black/
2020-04-21 21:00:05 0 cats/white/
2020-04-21 21:00:04 0 cats/
2020-04-21 21:00:03 0 dogs/cute/
2020-04-21 21:00:04 0 dogs/fierce/
2020-04-21 21:00:02 0 dogs/
我想在 S3 中创建以下文件夹结构,
/demo/app/a.txt
通过控制台:
demo
和 app
使用“创建文件夹”,然后 a.txt
文件上传
通过 CLI:
aws s3 sync . s3://<my-bucket>/
,其中 .
(当前目录)有 demo
个文件夹
--
现在当我运行,
aws s3 ls s3://<my-bucket> --recursive
,结果相当interesting/puzzling!
输出:
# created & uploaded from console
demo/
demo/app/
demo/app/a.txt
# from CLI
demo/app/a.txt
显然,demo/
和 demo/app/
没有任何 prefixes/objects 使用 CLI 上传创建。
--
那么,如何模仿 CLI 上传的 0 字节 文件行为?也就是说,匹配前缀!
另一个用例是,由于前缀不可用,无法从浏览器浏览目录。例如
- 从控制台上传:
https://<domain>/demo/
显示app
目录。 - 从 CLI 上传:
https://<domain>/demo/
结果为NoSuchKeyError
--
注意:我正在使用 CloudFront
分发来访问 S3 数据(如果有帮助的话)!
Amazon S3 是一个平面对象存储系统。它不是文件系统,也没有文件夹或目录的概念。相反,对象的 Key
(文件名)包含对象的 完整路径 。
使用 S3 的最简单方法是假装文件夹存在,但实际上并不创建它们。例如,您可以像这样将文件复制到 S3:
aws s3 cp a.txt s3://my-bucket/demo/app/a.txt
这将成功运行,即使没有名为 demo
或 app
的目录,因为 directories/folders 不存在 .
相反,Amazon S3 提供了 CommonPrefix
的概念,您将在 ListObjects()
API 调用的底部看到它。此 returns 由 分隔符 (通常为 /
)分隔的类似文件夹的名称列表。这提供了目录的编程等效性,而不需要它们实际存在。
如果您希望呈现一系列分层目录,请使用 CommonPrefixes
的列表来构建该视图。即使没有零长度文件,这也会起作用,因为 S3 查看对象的键,而不是实际目录。
这里有一些例子:
aws s3 cp a.txt s3://my-bucket/demo/app/a.txt
upload: ./a.txt to s3://my-bucket/demo/app/a.txt
aws s3api list-objects-v2 --bucket my-bucket
{
"Contents": [
{
"Key": "demo/app/a.txt",
"LastModified": "2020-04-22T01:11:20+00:00",
"ETag": "\"802776735eb3ddcf03962ae47e08ed13\"",
"Size": 211,
"StorageClass": "STANDARD"
}
]
}
aws s3api list-objects-v2 --bucket my-bucket --delimiter '/'
{
"CommonPrefixes": [
{
"Prefix": "demo/"
}
]
}
aws s3api list-objects-v2 --bucket jstack-b --delimiter '/' --prefix 'demo/'
{
"CommonPrefixes": [
{
"Prefix": "demo/app/"
}
]
}
请注意末尾的命令如何提供 delimiter
,因此会返回 CommonPrefixes
的列表。您可以通过这种方式遍历目录列表(不存在)。
如果您确实需要在 S3 中存在一个反映本地文件夹结构的文件夹结构,那么您可以尝试以下 shell 脚本和 Linux 或 [=45 上的 awscli 的一些变体=]:
- 列出所有本地文件夹
- 将该列表转换为与 S3 命名约定匹配的内容
- 在 S3 中的每个文件夹名称处创建一个零字节文件
列出本地文件夹:
find . -type d
示例输出:
.
./dogs
./dogs/cute
./dogs/fierce
./cats
./cats/white
./cats/black
转换该列表以删除 .
,以便 ./dogs/cute
变为 dogs/cute
:
find . -type d | grep -v '^\.$' | sed 's/^\.\///g'
示例输出:
dogs
dogs/cute
dogs/fierce
cats
cats/white
cats/black
最后将它们放在一起并在每个文件夹中创建零字节文件:
find . -type d \
| grep -v '^\.$' \
| sed 's/^\.\///g' \
| xargs -L 1 -I % \
aws s3api put-object --bucket mybucket --key %/ --content-length 0
检查 S3 中的结果:
aws s3 ls s3://mybucket --recursive
结果:
2020-04-21 21:00:05 0 cats/black/
2020-04-21 21:00:05 0 cats/white/
2020-04-21 21:00:04 0 cats/
2020-04-21 21:00:03 0 dogs/cute/
2020-04-21 21:00:04 0 dogs/fierce/
2020-04-21 21:00:02 0 dogs/