如何仅显示来自 aws s3 ls 命令的文件?

Posted

技术标签:

【中文标题】如何仅显示来自 aws s3 ls 命令的文件?【英文标题】:How to display only files from aws s3 ls command? 【发布时间】:2016-08-17 05:39:36 【问题描述】:

我正在使用 aws cli 使用以下命令 (documentation) 列出 s3 存储桶中的文件:

aws s3 ls s3://mybucket --recursive --human-readable --summarize

这个命令给了我以下输出:

2013-09-02 21:37:53   10 Bytes a.txt
2013-09-02 21:37:53  2.9 MiB foo.zip
2013-09-02 21:32:57   23 Bytes foo/bar/.baz/a
2013-09-02 21:32:58   41 Bytes foo/bar/.baz/b
2013-09-02 21:32:57  281 Bytes foo/bar/.baz/c
2013-09-02 21:32:57   73 Bytes foo/bar/.baz/d
2013-09-02 21:32:57  452 Bytes foo/bar/.baz/e
2013-09-02 21:32:57  896 Bytes foo/bar/.baz/hooks/bar
2013-09-02 21:32:57  189 Bytes foo/bar/.baz/hooks/foo
2013-09-02 21:32:57  398 Bytes z.txt

Total Objects: 10
   Total Size: 2.9 MiB

但是,这是我想要的输出:

a.txt
foo.zip
foo/bar/.baz/a
foo/bar/.baz/b
foo/bar/.baz/c
foo/bar/.baz/d
foo/bar/.baz/e
foo/bar/.baz/hooks/bar
foo/bar/.baz/hooks/foo
z.txt

如何省略日期、时间和文件大小以仅显示文件列表?

【问题讨论】:

【参考方案1】:

如果您的文件没有空格,那么这是最简单的方法:

aws s3 ls s3://mybucket  | cut -c32-

输出是:

1.txt.gz
2.txt.gz
3.txt.gz

代替:

2021-12-15 23:05:44         36 1.txt.gz
2021-12-15 23:05:45         37 2.txt.gz
2021-12-15 23:05:46         39 3.txt.gz

【讨论】:

【参考方案2】:

它只是通过起始符号过滤的grep。 “^-”表示行以“-”符号开头。另一方面,目录以字母“d”开头

ls -Al | grep "^-"

【讨论】:

【参考方案3】:

编辑:在考虑了 MultiDev 的评论后,之前的解决方案不适用于其中包含空格的对象。我用s3api代替s3

aws s3api list-objects --bucket mybucket --prefix myprefix --query 'Contents[].Key' | jq -rc '.[]'

前缀是可选的

使用jq 从返回的数组中获取原始元素(键)

使用--query 'Contents[].Key: Key, Size: Size' 之类的内容获取更多信息,然后使用jq 进一步格式化输出


旧解决方案:aws s3 ls s3://mybucket --recursive | rev | cut -d" " -f1 | rev

我建议不要依赖间距并获取第 4 个字段。

从技术上讲,您想要最后一个字段,无论它在哪个位置。

因此,使用rev 更安全...rev 按字符反转字符串输入字符 因此,当您通过管道将 aws s3 ls 输出到 rev 时,所有内容都会颠倒过来,包括字段的位置,因此最后一个字段总是成为第一个字段。 无需弄清楚最后一个字段的位置,您只需 rev,首先获得,然后再次获得 rev,因为该字段中的字符也会颠倒。

例子:

2013-09-02 21:32:57 23 Bytes foo/bar/.baz/a 变为 a/zab./rab/oof setyB 32 75:23:12 20-90-3102

然后cut -d" " -f1 将检索第一个字段a/zab./rab/oof

然后再次rev 得到foo/bar/.baz/a

【讨论】:

很棒的概念,但是当文件名中有空格时不起作用。 True... 这应该可以工作:aws s3api list-objects --bucket mybucket --prefix myprefix --query 'Contents[].Key' | jq -rc '.[]'【参考方案4】:
How to display only files from aws s3 ls command?

1. Basic command

$ aws s3 ls s3://bucket --recursive

output :

2021-02-10 15:29:02          0 documents/
2021-02-10 15:29:02         18 documents/data/data.txt
2021-03-15 23:35:12          0 documents/data/my code.txt


2. To get only keys from s3 bucket containing spaces also.

$ aws s3 ls s3://bucket --recursive | awk ' $1=$2=$3=""; print $0' | cut -c4-

output : 

documents/
documents/data/data.txt
documents/data/my code.txt

3. Removing "documents/" from result

$ aws s3 ls s3://bucket --recursive | awk '$0 !~ /\/$/  $1=$2=$3=""; print $0' | cut -c4-

output :

documents/data/data.txt
documents/data/my code.txt

【讨论】:

【参考方案5】:

一个 S3 存储桶不仅可以包含文件,还可以包含带有前缀的文件。如果您使用--recursive,它不仅会列出文件,还会列出前缀。如果您不关心前缀而只关心存储桶中的文件或只关心存储桶中的前缀,这应该可以工作。

aws s3 ls s3://$S3_BUCKET/$S3_OPTIONAL_PREFIX/ --recursive | awk ' if($3 >0) print $4'

awk$3 是文件的大小,如果前缀为0。也可能是文件为空,因此它也会跳过空文件。

【讨论】:

【参考方案6】:

将 s3api 与 jq (AWS docu aws s3api list-objects) 一起使用:

这种模式总是递归的。

$ aws s3api list-objects --bucket "bucket" | jq -r '.Contents[].Key'
a.txt
foo.zip
foo/bar/.baz/a
[...]

您可以通过添加前缀来过滤子目录(此处为foo 目录)。前缀不能以 / 开头。

$ aws s3api list-objects --bucket "bucket" --prefix "foo/" | jq -r '.Contents[].Key'
foo/bar/.baz/a
foo/bar/.baz/b
foo/bar/.baz/c
[...]

jq 选项:

-r = 原始模式,输出中没有引号 .Contents[] = 获取 Contents 对象数组内容 .Key = 获取每个关键字段(不生成有效的 JSON 数组,但我们处于原始模式,所以我们不在乎)

附录

您可以使用纯 AWS CLI,但这些值将由 \x09 = Horizo​​ntal Tab (AWS: Controlling Command Output from the AWS CLI - Text Output Format) 分隔

$ aws s3api list-objects --bucket "bucket" --prefix "foo/" --query "Contents[].Key" --output text
foo/bar/.baz/a   foo/bar/.baz/b   foo/bar/.baz/c   [...]

AWS CLI 选项:

--query "Contents[].Key" = 查询内容对象数组并获取其中的每个键 --output text = 输出为制表符分隔的文本,带有现在的引号

基于李光阳评论的补充

带有新行的纯 AWS CLI:

$ aws s3api list-objects --bucket "bucket" --prefix "foo/" --query "Contents[].Key: Key" --output text
foo/bar/.baz/a
foo/bar/.baz/b
foo/bar/.baz/c
[...]

【讨论】:

非常好。或aws s3api list-buckets | jq -r '.Buckets[].Name' 我喜欢纯 AWS CLI,实际上您可以使用 --query 'Contents[].Key: Key' 来实现。然后每行一条记录。【参考方案7】:

我的解决方案

使用 aws cli 递归地仅列出文件。

aws s3 ls s3://myBucket --recursive | awk 'NF>1print $4' | grep .

grep . - 清除空行。


示例:aws s3 ls s3://myBucket

                           PRE f5c10c1678e8484482964b8fdcfe43ad/
                           PRE f65b94ad31734135a61a7fb932f7054d/
                           PRE f79b12a226b542dbb373c502bf125ffb/
                           PRE logos/
                           PRE test/
                           PRE userpics/
2019-05-14 10:56:28       7754 stage.js

解决方案:aws s3 ls s3://myBucket --recursive | awk 'NF>1print $4' | grep .

stage.js

【讨论】:

在文件名中包含“ChatNotes 8Mar.txt”等空格时不起作用。此代码仅打印“ChatNotes”【参考方案8】:

您不能仅使用aws 命令来执行此操作,但您可以轻松地将其通过管道传递给另一个命令以去除您不想要的部分。您还需要删除 --human-readable 标志以使输出更易于使用,并删除 --summarize 标志以删除最后的摘要数据。

试试这个:

aws s3 ls s3://mybucket --recursive | awk 'print $4'

编辑:考虑文件名中的空格:

aws s3 ls s3://mybucket --recursive | awk '$1=$2=$3=""; print $0' | sed 's/^[ \t]*//'

【讨论】:

@MichalGasek 如果您像我指定的那样删除 --human-readable 标志,那么它是 4 美元,而不是 5 美元。 真的不认为值得另一个答案。例如,在第三个空格之后通过 perl 管道和匹配可以正常工作:aws s3 ls s3://mybucket --recursive | perl -ne '($key)=$_=~/^[\d\-]+\s+[\d\:]+\s+\d+\s(.+?)$/g; print "$key\n";' 替代非 awk 解决方案:aws s3 ls s3://mybucket --recursive | tr -s ' ' | cut -d' ' -f4 我无法验证这是否适用于递归,但由于“简单”版本不适用于文件名中的空格,它似乎是一个脆弱的解决方案,而另一个则是不必要的复杂。相反,切掉字符,这在 CLI 输出格式更改之前应该足够健壮:aws s3 ls s3://mybucket | cut -c32-(可选添加递归并验证它仍然有效) 并非所有英雄都穿斗篷【参考方案9】:

仅对于 文件 名称,我发现最简单的是:

aws s3 ls s3://path/to/bucket/ | cut -d " " -f 4

这将在空格处截断返回的输出 (cut -d " "),并返回第四列 (-f 4),即文件名列表。

【讨论】:

对我来说,这似乎不像 awk 解决方案那样始终如一。 与 --human-readable... 分开编辑:实际上也没有。【参考方案10】:

一个简单的过滤器是:

aws s3 ls s3://mybucket --recursive | perl -pe 's/^(?:\S+\s+)3//'

这将删除日期、时间和大小。只留下文件的完整路径。它也可以在没有递归的情况下工作,它也应该适用于包含空格的文件名。

【讨论】:

谢谢。这与空格甚至文件名中的制表符完美配合。节省大量时间和精力。【参考方案11】:

简单方法

aws s3 ls s3://mybucket --recursive --human-readable --summarize|cut -c 29-

【讨论】:

目前,对我来说,aws s3 ls 的输出结果是你想要剪掉-c32,而不是-c29;不确定是我的数据还是输出格式的变化。 (我实际上没有子文件夹。)--human-readable 或纯默认输出都是如此;列是同一个地方。但实际上,在这种情况下不需要人类可读。无论哪种情况,您都想省略--summarize。简而言之,aws s3 ls s3://mybucket | cut -c32-(和 --recursive 仅在需要时) 请注意,如果文件名中有空格,则此处尝试基于空格(awk、cut 等)进行剪切的所有其他答案都将不起作用。 这是最干净的方法(对于带有 -c32 的 michael)【参考方案12】:

简单的命令是

aws s3 ls s3://mybucket --recursive --human-readable --summarize |cut -d ' ' -f 8

如果您需要时间戳,只需更新命令字段值。

【讨论】:

以上是关于如何仅显示来自 aws s3 ls 命令的文件?的主要内容,如果未能解决你的问题,请参考以下文章

AWS仅允许来自S3的EC2流量

如何修复 AWS Glue 代码以显示来自 AWS S3 的分区表的计数和架构

aws s3 ls 的 boto3 等价物是啥?

来自 S3 的 AWS Redshift COPY csv

如何使用 CloudFront 从 AWS S3 安全地播放 .m3u8 流文件?

AWS S3 CLI - 如何使用存储桶上设置的所有当前策略获取 JSON?