如何按修改日期列出Amazon S3的内容?

azh*_*22k 25 amazon-s3 amazon-web-services aws-cli

大多数情况下,我们将文件加载到一个公共S3存储桶中,因此很难在其中找出数据.

如何查看特定日期上传的对象?

Fré*_*nri 23

一种解决方案可能会使用s3api.如果您的对象少于1000个,则可以轻松工作,否则您需要使用分页.

s3api可以列出所有对象,并具有lastmodifieds3中导入的键属性的属性.然后可以对其进行排序,在日期之后或之前查找文件,匹配日期......

运行此类选项的示例

  1. 给定日期的所有文件

    DATE=$(date +%Y-%m-%d)
    aws s3api list-objects-v2 --bucket test-bucket-fh --query 'Contents[?contains(LastModified, `$DATE`)]'
    
    Run Code Online (Sandbox Code Playgroud)
  2. 某个日期之后的所有文件

    export YESTERDAY=`date -v-1w +%F`
    aws s3api list-objects-v2 --bucket test-bucket-fh --query 'Contents[?LastModified > `$YESTERDAY`]'
    
    Run Code Online (Sandbox Code Playgroud)

s3api将返回一些元数据,以便您可以筛选特定元素

DATE=$(date +%Y-%m-%d)
aws s3api list-objects-v2 --bucket test-bucket-fh --query 'Contents[?contains(LastModified, `$DATE`)].Key'
Run Code Online (Sandbox Code Playgroud)

  • @NicholasPorter awscli 的 `--query` 选项是在客户端实现的,不是吗?我不明白这种方法会比其他建议的方法更便宜。 (6认同)
  • 这应该是一个选择的答案。其他答案建议“ls”桶中的对象然后进行排序,这将是昂贵的。 (4认同)

Die*_*lez 10

在给定日期搜索

aws s3api list-objects-v2 --bucket BUCKET_NAME --query 'Contents[?contains(LastModified, `YYYY-MM-DD`)].Key'
Run Code Online (Sandbox Code Playgroud)

搜索从某个日期到今天

aws s3api list-objects-v2 --bucket BUCKET_NAME  --query 'Contents[?LastModified>=`YYYY-MM-DD`].Key'
Run Code Online (Sandbox Code Playgroud)

您可以选择.Key从查询末尾删除 以从 s3 对象中获取所有元数据字段

  • 这是最好的答案。简单又有效 (5认同)
  • 请注意,如果您想查询存储桶中的特定“文件夹”,请使用“--prefix”选项。例如。`--前缀“文件夹/子文件夹`” (4认同)

小智 9

以下命令适用于 Linux。

aws s3 ls --recursive s3:// <your s3 path here> | awk '$1 > "2018-10-13 00:00:00" {print $0}' | sort -n
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助!!!

  • 请注意,如果桶中有很多对象,这种方法会很昂贵。您仍然需要为列出对象付费。查看下面@frédéric-henri 的回答。 (5认同)

azh*_*22k 8

在linux中执行此操作的简单方法如下:

DATE=$(date +%Y-%m-%d)
aws s3 ls s3://<your s3 path here>/ | grep $DATE
Run Code Online (Sandbox Code Playgroud)


sag*_*e88 8

如果它将来对任何人有帮助,这里有一个 python 程序,它允许您按一组前缀、后缀和/或上次修改日期进行过滤。请注意,您需要正确设置 aws 凭据才能使用 boto3。请注意,这支持包含超过 1000 个键的前缀。

用法:

python save_keys_to_file.py -b 'bucket_name' -p some/prefix -s '.txt' '.TXT' -f '/Path/To/Some/File/test_keys.txt' -n '2018-1-1' -x '2018-2-1'
Run Code Online (Sandbox Code Playgroud)

代码文件名:save_keys_to_file.py

import argparse
import boto3
import dateutil.parser
import logging
import pytz
from collections import namedtuple

logger = logging.getLogger(__name__)


Rule = namedtuple('Rule', ['has_min', 'has_max'])
last_modified_rules = {
    Rule(has_min=True, has_max=True):
        lambda min_date, date, max_date: min_date <= date <= max_date,
    Rule(has_min=True, has_max=False):
        lambda min_date, date, max_date: min_date <= date,
    Rule(has_min=False, has_max=True):
        lambda min_date, date, max_date: date <= max_date,
    Rule(has_min=False, has_max=False):
        lambda min_date, date, max_date: True,
}


def get_s3_objects(bucket, prefixes=None, suffixes=None, last_modified_min=None, last_modified_max=None):
    """
    Generate the objects in an S3 bucket. Adapted from:
    https://alexwlchan.net/2017/07/listing-s3-keys/

    :param bucket: Name of the S3 bucket.
    :ptype bucket: str
    :param prefixes: Only fetch keys that start with these prefixes (optional).
    :ptype prefixes: tuple
    :param suffixes: Only fetch keys that end with thes suffixes (optional).
    :ptype suffixes: tuple
    :param last_modified_min: Only yield objects with LastModified dates greater than this value (optional).
    :ptype last_modified_min: datetime.date
    :param last_modified_max: Only yield objects with LastModified dates greater than this value (optional).
    :ptype last_modified_max: datetime.date

    :returns: generator of dictionary objects
    :rtype: dict https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.list_objects
    """
    if last_modified_min and last_modified_max and last_modified_max < last_modified_min:
        raise ValueError(
            "When using both, last_modified_max: {} must be greater than last_modified_min: {}".format(
                last_modified_max, last_modified_min
            )
        )
    # Use the last_modified_rules dict to lookup which conditional logic to apply
    # based on which arguments were supplied
    last_modified_rule = last_modified_rules[bool(last_modified_min), bool(last_modified_max)]

    if not prefixes:
        prefixes = ('',)
    else:
        prefixes = tuple(set(prefixes))
    if not suffixes:
        suffixes = ('',)
    else:
        suffixes = tuple(set(suffixes))

    s3 = boto3.client('s3')
    kwargs = {'Bucket': bucket}

    for prefix in prefixes:
        kwargs['Prefix'] = prefix
        while True:
            # The S3 API response is a large blob of metadata.
            # 'Contents' contains information about the listed objects.
            resp = s3.list_objects_v2(**kwargs)
            for content in resp.get('Contents', []):
                last_modified_date = content['LastModified']
                if (
                    content['Key'].endswith(suffixes) and
                    last_modified_rule(last_modified_min, last_modified_date, last_modified_max)
                ):
                    yield content

            # The S3 API is paginated, returning up to 1000 keys at a time.
            # Pass the continuation token into the next response, until we
            # reach the final page (when this field is missing).
            try:
                kwargs['ContinuationToken'] = resp['NextContinuationToken']
            except KeyError:
                break


def get_s3_keys(bucket, prefixes=None, suffixes=None, last_modified_min=None, last_modified_max=None):
    """
    Generate the keys in an S3 bucket.

    :param bucket: Name of the S3 bucket.
    :ptype bucket: str
    :param prefixes: Only fetch keys that start with these prefixes (optional).
    :ptype prefixes: tuple
    :param suffixes: Only fetch keys that end with thes suffixes (optional).
    :ptype suffixes: tuple
    :param last_modified_min: Only yield objects with LastModified dates greater than this value (optional).
    :ptype last_modified_min: datetime.date
    :param last_modified_max: Only yield objects with LastModified dates greater than this value (optional).
    :ptype last_modified_max: datetime.date
    """
    for obj in get_s3_objects(bucket, prefixes, suffixes, last_modified_min, last_modified_max):
        yield obj['Key']


def valid_datetime(date):
    if date is None:
        return date
    try:
        utc = pytz.UTC
        return utc.localize(dateutil.parser.parse(date))
    except Exception:
        raise argparse.ArgumentTypeError("Could not parse value: '{}' to type datetime".format(date))


def main():
    FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    logging.basicConfig(format=FORMAT)
    logger.setLevel(logging.DEBUG)

    parser = argparse.ArgumentParser(description='List keys in S3 bucket for prefix')
    parser.add_argument('-b', '--bucket', help='S3 Bucket')
    parser.add_argument('-p', '--prefixes', nargs='+', help='Filter s3 keys by a set of prefixes')
    parser.add_argument('-s', '--suffixes', nargs='*', help='Filter s3 keys by a set of suffixes')
    parser.add_argument('-n', '--last_modified_min', default=None, type=valid_datetime, help='Filter s3 content by minimum last modified date')
    parser.add_argument('-x', '--last_modified_max', default=None, type=valid_datetime, help='Filter s3 content by maximum last modified date')
    parser.add_argument('-f', '--file', help='Optional: file to write keys to.', default=None)

    args = parser.parse_args()
    logger.info(args)
    keys = get_s3_keys(args.bucket, args.prefixes, args.suffixes, args.last_modified_min, args.last_modified_max)

    open_file = open(args.file, 'w') if args.file else None
    try:
        counter = 0
        for key in keys:
            print(key, file=open_file)
            counter += 1
    finally:
        open_file.close()

    logger.info('Retrieved {} keys'.format(counter))


if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)


Rom*_* K. 7

顺便说一句,如果您想在日期之间进行搜索,这适用于 Windows

aws s3api list-objects-v2 --max-items 10 --bucket "BUCKET" --query "Contents[?LastModified>='2019-10-01 00:00:00'] | [?LastModified<='2019-10-30 00:00:00'].{ Key: Key, Size: Size, LastModified: LastModified }"


Gui*_*rez 7

如果您有大量文件(数百万或数十亿条目),最好的方法是使用Amazon S3 Inventory生成存储桶清单(包括 Last Modified 字段),然后使用 SQL 查询通过Amazon Athena查询生成的清单。

您可以在此处找到详细的演练:https://aws.amazon.com/blogs/storage/manage-and-analyze-your-data-at-scale-using-amazon-s3-inventory-and-amazon-athena/


Tim*_*Tim 5

这不是通用解决方案,但在您的对象基于日期命名的情况下可能会有所帮助 - 例如 CloudTrail 日志。例如,我想要一个在 2019 年 6 月创建的对象列表。

aws s3api list-objects-v2 --bucket bucketname --prefix path/2019-06
Run Code Online (Sandbox Code Playgroud)

这在服务器端进行过滤。使用“查询”参数的缺点是它会下载大量数据以在客户端进行过滤。这意味着潜在的大量 API 调用需要花钱,并且您需要支付额外的 AWS 数据输出费用。

来源:https : //github.com/aws/aws-sdk-js/issues/2543


k-s*_*ver 5

看起来没有 API 可以让您在服务器端按修改日期进行过滤。所有过滤似乎都发生在客户端,因此无论您使用什么客户端(s3api、boto3 等),如果您必须对大量文件执行此操作,速度都会很慢。没有好的选择可以并行化该扫描,除非您可以通过在不同的子文件夹上运行列表操作来实现这一点,但这在很多情况下肯定行不通。

我发现实际上让您能够按修改日期过滤大量文件的唯一选择是使用 AWS S3 清单 - https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-库存.html。这样,AWS 会为您运行 S3 文件索引,并将文件的元数据(即文件路径、上次修改日期、大小等)存储在指定的 S3 位置。您可以轻松地使用它按修改日期进行过滤。