AWS S3:如何使用bash检查存储桶中是否存在文件

J. *_*len 20 bash amazon-s3 amazon-web-services

我想知道是否可以检查某个存储桶中是否存在某些文件.

这就是我发现的:

使用s3cmd检查文件是否在S3存储桶中

它应该解决我的问题,但由于某种原因它不断返回该文件不存在,而它确实存在.这个解决方案也有点过时,不使用该doesObjectExist方法.

可以在Amazon S3 Web服务中使用的所有方法的摘要

这给出了如何使用此方法的语法,但我似乎无法使其工作.

他们是否希望您创建一个布尔变量来保存方法的状态,或者该函数是否直接为您提供输出/抛出错误?

这是我目前在我的bash脚本中使用的代码:

existBool=doesObjectExist(${BucketName}, backup_${DomainName}_${CurrentDate}.zip)

if $existBool ; then
        echo 'No worries, the file exists.'
fi
Run Code Online (Sandbox Code Playgroud)

我只使用文件名来测试它,而不是给出完整路径.但由于我得到的错误是语法错误,我可能只是错误地使用它.

希望有人可以帮助我,告诉我我做错了什么.

!编辑

我最终寻找另一种方法来做到这一点,因为使用doesObjectExist不是最快或最简单的.

Dav*_*ple 22

上次我看到性能比较getObjectMetadata是检查对象是否存在的最快方法.使用AWS cli作为head-object方法,示例:

aws s3api head-object --bucket www.codeengine.com --key index.html
Run Code Online (Sandbox Code Playgroud)

返回:

{
    "AcceptRanges": "bytes",
    "ContentType": "text/html; charset=utf-8",
    "LastModified": "Sun, 08 Jan 2017 22:49:19 GMT",
    "ContentLength": 38106,
    "ContentEncoding": "gzip",
    "ETag": "\"bda80810592763dcaa8627d44c2bf8bb\"",
    "StorageClass": "REDUCED_REDUNDANCY",
    "CacheControl": "no-cache, no-store",
    "Metadata": {}
}
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个,因为它还验证你正在检查的是一个对象.使用aws s3 ls在这方面有点过于宽容. (3认同)

小智 14

请注意,即使答案被接受,"aws s3 ls"仍然不能正常工作.它按前缀搜索,而不是按特定对象键搜索.当有人通过在文件名的末尾添加"1"来重命名文件时,我发现这很难,并且存在检查仍将返回True.

(试图将其添加为评论,但还没有足够的代表.)

  • 我刚刚注意到这种完全相同的行为,这就是我提出这个问题的原因。 (2认同)

Amr*_*mri 8

我通常使用set -eufo pipefail以下方法对我来说效果更好,因为我不需要担心未设置的变量或整个脚本退出。

object_exists=$(aws s3api head-object --bucket $bucket --key $key || true)
if [ -z "$object_exists" ]; then
  echo "it does not exist"
else
  echo "it exists"
fi
Run Code Online (Sandbox Code Playgroud)


tra*_*ula 7

一种简单的方法是使用 aws s3 ls

exists=$(aws s3 ls $path_to_file)
if [ -z "$exists" ]; then
  echo "it does not exist"
else
  echo "it exists"
fi
Run Code Online (Sandbox Code Playgroud)

  • 对不起,如果我听起来太苛刻,但由于其他两个帖子中解释的原因,这不应该被接受作为答案. (6认同)
  • 如果您有具有相同前缀的文件,则此解决方案无法正常工作。当存储桶“s3://bucket/file.txt.gz”中存在文件时,“s3://bucket/file.txt”将被视为存在。head-object 方法可能是一种正确的方法,但它迫使您将 `s3://` uri 分成不同的部分。 (2认同)

Arj*_*ijk 6

该语句将返回一个trueorfalse响应:

aws s3api list-objects-v2 \
  --bucket <bucket_name> \
  --query "contains(Contents[].Key, '<object_name>')"
Run Code Online (Sandbox Code Playgroud)

因此,对于问题中提供的示例:

aws s3api list-objects-v2 \
  --bucket ${BucketName} \
  --query "contains(Contents[].Key, 'backup_${DomainName}_${CurrentDate}.zip')"
Run Code Online (Sandbox Code Playgroud)

我喜欢这种方法,因为:

  • --query 选项使用 JMESPath 语法进行客户端过滤,这里详细记录了如何使用它。

  • 由于 --query 选项内置于 aws cli 中,因此无需安装其他依赖项。

  • 您可以首先运行不带 --query 选项的命令,例如:

      aws s3api list-objects-v2 --bucket <bucket_name> 
    
    Run Code Online (Sandbox Code Playgroud)

    它会返回一个格式良好的 JSON,类似于:

{
    "Contents": [
        {
            "Key": "my_file_1.tar.gz",
            "LastModified": "----",
            "ETag": "\"-----\"",
            "Size": -----,
            "StorageClass": "------"
        },
        {
            "Key": "my_file_2.txt",
            "LastModified": "----",
            "ETag": "\"----\"",
            "Size": ----,
            "StorageClass": "----"
        },
        ...
    ]
}
Run Code Online (Sandbox Code Playgroud)
  • 然后,您可以设计适当的查询。在这种情况下,您想要检查 JSON 是否包含列表Contents以及该列表中的项目是否Key与您的文件(对象)名称相同:

    --query "contains(Contents[].Key, '<object_name>')"
    
    Run Code Online (Sandbox Code Playgroud)


Ita*_*ayB 5

继@DaveMaple和@MichaelGlenn答案之后,这是我使用的条件:

aws s3api head-object --bucket <some_bucket> --key <some_key> || not_exist=true
if [ $not_exist ]; then
  echo "it does not exist"
else
  echo "it exists"
fi
Run Code Online (Sandbox Code Playgroud)

  • @JohnMellor 将 `&gt; /dev/null 2&gt;&amp;1` 添加到第一个命令:`aws s3api head-object --bucket &lt;some_bucket&gt; --key &lt;some_key&gt; &gt; /dev/null 2&gt;&amp;1 || not_exist=true` (3认同)