大多数时候,我们会在公共 S3 存储桶中加载文件,因此很难找出其中的数据。
如何查看特定日期上传的对象?
s3api
。如果您的对象少于 1000 个,那么它很容易工作,否则您需要使用分页。
s3api
可以列出所有对象,并且具有 s3 中导入的键的 lastmodified
属性的属性。然后可以对其进行排序,查找日期之后或之前的文件,匹配日期......
运行此类选项的示例
DATE=$(date +%Y-%m-%d)
bucket=test-bucket-fh
aws s3api list-objects-v2 --bucket "$bucket" \
--query 'Contents[?contains(LastModified, `'"$DATE"'`)]'
SINCE=`date --date '-2 weeks +2 days' +%F 2>/dev/null || date -v '-2w' -v '+2d' +%F`
# ^^^^ GNU style ^^^^ BSD style
bucket=test-bucket-fh
aws s3api list-objects-v2 --bucket "$bucket" \
--query 'Contents[?LastModified > `'"$SINCE"'`]'
s3api 将返回一些元数据,以便您可以过滤特定元素
DATE=$(date +%Y-%m-%d)
bucket=test-bucket-fh
aws s3api list-objects-v2 --bucket "$bucket" \
--query 'Contents[?contains(LastModified, `'"$DATE"'`)].Key'
在给定日期搜索
aws s3api list-objects-v2 --bucket BUCKET_NAME --query 'Contents[?contains(LastModified, `YYYY-MM-DD`)].Key'
搜索从某个日期到今天
aws s3api list-objects-v2 --bucket BUCKET_NAME --query 'Contents[?LastModified>=`YYYY-MM-DD`].Key'
您可以选择删除查询末尾的
.Key
,以从 s3 对象中获取所有元数据字段
如果它对将来的任何人有帮助,这里有一个 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'
代码文件名: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()
顺便说一句,如果您想在日期之间进行搜索,这适用于 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 }"
这不是通用解决方案,但在根据日期命名对象(例如 CloudTrail 日志)时很有用。例如,我想要 2019 年 6 月创建的对象列表。
aws s3api list-objects-v2 --bucket bucketname --prefix path/2019-06
这在服务器端进行过滤。使用“query”参数的缺点是它会下载大量数据以在客户端进行过滤。这意味着可能需要大量的 API 调用(这会产生费用),并且需要您付费才能从 AWS 流出额外的数据。
以下命令适用于 Linux。
aws s3 ls --recursive s3:// <your s3 path here> | awk '$1 > "2018-10-13 00:00:00" {print $0}' | sort -n
我希望这有帮助!!!
如果您有大量文件(数百万或数十亿条条目),最好的方法是使用 Amazon S3 Inventory 生成存储桶清单,包括 Last Modified 字段,然后通过 Amazon Athena 查询生成的清单 使用 SQL 查询。
您可以在此处找到详细的演练:https://aws.amazon.com/blogs/storage/manage-and-analyze-your-data-at-scale-using-amazon-s3-inventory-and-amazon-雅典娜/
看起来没有 API 可以让您在服务器端按修改日期进行过滤。所有过滤似乎都发生在客户端,因此无论您使用什么客户端(s3api、boto3 等),如果您必须对大量文件执行此操作,速度都会很慢。没有好的选择可以并行化该扫描,除非您可以通过在不同的子文件夹上运行列表操作来做到这一点,但这在很多情况下肯定行不通。
我发现真正能够让您按修改日期过滤大量文件的唯一选择是使用 AWS S3 清单 - https://docs.aws.amazon.com/AmazonS3/latest/userguide/ storage-inventory.html。这样,AWS 就会为您运行 S3 文件索引,并将文件的元数据(即文件路径、上次修改日期、大小等)存储在指定的 S3 位置。您可以轻松地使用它按修改日期进行过滤。
如果为存储桶启用了版本控制,并且您想要在特定日期之后恢复最新删除的对象,请使用以下命令:
$ aws s3api list-object-versions --bucket mybucket --prefix myprefix/ --output json --query 'DeleteMarkers[?LastModified>=`2020-07-07T00:00:00` && IsLatest==`true`].[Key,VersionId]' | jq -r '.[] | "--key '\''" + .[0] + "'\'' --version-id " + .[1]' |xargs -L1 aws s3api delete-object --bucket mybucket
这意味着您已经安装了
aws cli
(我使用的是v.2.0.30)和jq
。
如果您想在删除之前确定一切正常,只需在
echo
之前使用 aws
:
$ aws s3api list-object-versions --bucket mybucket --prefix myprefix/ --output json --query 'DeleteMarkers[?LastModified>=`2020-07-07T00:00:00` && IsLatest==`true`].[Key,VersionId]' | jq -r '.[] | "--key '\''" + .[0] + "'\'' --version-id " + .[1]' |xargs -L1 echo aws s3api delete-object --bucket mybucket > files.txt
请注意,由于
echo
,引号将无法正确应用并保存在没有它的文件中。如果路径中没有空格就可以。
您可以检查该文件,如果一切正常,请按以下方式运行:
$ cat files.txt | bash
如果为存储桶启用了版本控制,并且您想要列出特定日期之后最后修改的对象,则命令如下:
$ aws s3api list-objects-v2 --bucket "bucket_name" --prefix "prefix" --query "Contents[?LastModified>='2023-01-23'].{key: Key, date: LastModified}"
当我们不确定开始日期时。只需要在开始时创建的前 10 个对象即可。
aws s3api list-objects --bucket your-bucket-name --prefix your-prefix --query "Contents[?LastModified!=null].{Key: Key, LastModified: LastModified}" --output json | grep -v '"LastModified": null' | jq 'sort_by(.LastModified) | .[:10]'