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

时间:2017-01-26 10:55:38

标签: bash amazon-web-services amazon-s3

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

这是我发现的:

Checking if a file is in a S3 bucket using the s3cmd

  

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

Summary of all the methods that can be used in the Amazon S3 web service

  

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

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

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

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

if $existBool ; then
        echo 'No worries, the file exists.'
fi

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

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

!修改

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

8 个答案:

答案 0 :(得分:10)

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

aws s3api head-object --bucket www.codeengine.com --key index.html

返回:

{
    "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": {}
}

答案 1 :(得分:10)

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

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

答案 2 :(得分: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

答案 3 :(得分:2)

我通常使用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

答案 4 :(得分:1)

在awscli中,我们执行 ls grep

示例:aws s3 ls s3:// <存储桶名称> | grep'文件名'

这可以包含在bash脚本中。

答案 5 :(得分:0)

下面是@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

答案 6 :(得分:0)

受上述答案的启发,我还用它来检查文件大小,因为我的存储桶被一些带有 404 个答案的脚本丢弃了。它需要 jq tho。

minsize=100
s3objhead=$(aws s3api head-object \
  --bucket "$BUCKET" --key "$KEY" 
  --output json || echo '{"ContentLength": 0}')

if [ $(printf "%s" "$s3objhead" | jq '.ContentLength') -lt "$minsize" ]; then
  # missing or small
else
  # exist and big
fi

答案 7 :(得分:0)

此语句将返回 truefalse 响应:

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

因此,如果是问题中提供的示例:

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

我喜欢这种方法,因为:

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

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

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

      aws s3api list-objects-v2 --bucket <bucket_name> 
    

    这将返回一个格式良好的 JSON,例如:

<块引用>
{
    "Contents": [
        {
            "Key": "my_file_1.tar.gz",
            "LastModified": "----",
            "ETag": "\"-----\"",
            "Size": -----,
            "StorageClass": "------"
        },
        {
            "Key": "my_file_2.txt",
            "LastModified": "----",
            "ETag": "\"----\"",
            "Size": ----,
            "StorageClass": "----"
        },
        ...
    ]
}
  • 这允许您设计适当的查询。在这种情况下,您要检查 JSON 是否包含列表 Contents 以及该列表中的项目是否具有与您的文件(对象)名称相同的 Key

    --query "contains(Contents[].Key, '<object_name>')"