AWS S3 File merge using CLI - amazon-web-services

I am trying to combine/merge contents from all the files existing in a S3 bucket folder into a new file. The combine/merge should be done by the ascending order of the Last modified of the S3 file.
I am able to do that manually by having hard coded file names like as follows:
(aws s3 cp s3://bucket1/file1 - && aws s3 cp s3://bucket1/file2 - && aws s3 cp s3://bucket1/file3 - ) | aws s3 cp - s3://bucket1/new-file
But, now I want to change the CLI command so that we can do this file merge based on list of as many files as they exist in a folder, sorted by Last Modified. So ideally, the cp command should receive the list of all files that exist in a S3 bucket folder, sorted by Last Modified and then merge them into a new file.
I appreciate everyone's help on this.

Give you some hints.
First list the files in the reverse order of Last Modified.
aws s3api list-objects --bucket bucket1 --query "reverse(sort_by(Contents,&LastModified))"
Then you should be fine to attach the rest commands as you did
aws s3api list-objects --bucket bucket1 --query "reverse(sort_by(Contents,&LastModified))" |jq -r .[].Key |while read file
do
echo $file
# do the cat $file >> new-file
done
aws s3 cp new-file s3://bucket1/new-file

Related

Copy the latest uploaded file from S3 bucket to local machine

I have a cron job set that moves the files from an EC2 instance to S3
aws s3 mv --recursive localdir s3://bucket-name/ --exclude "*" --include "localdir/*"
After that I use aws s3 sync s3://bucket-name/data1/ E:\Datafolder in .bat file and run task scheduler in Windows to run the command.
The issue is that s3 sync command copies all the files in /data1/ prefix.
So let's say I have the following files:
Day1: file1 is synced to local.
Day2: file1 and file2 are synced to local because file1 is removed from the local machine's folder.
I don't want them to occupy space on local machine. On Day 2, I just want file2 to be copied over.
Can this be accomplished by AWS CLI commands? or do I need to write a lambda function?
I followed the answer from Get last modified object from S3 using AWS CLI
but on Windows, the | and awk commands are not working as expected.
To obtain the name of the object that has the most recent Last Modified date, you can use:
aws s3api list-objects-v2 --bucket BUCKET-NAME --query 'sort_by(Contents, &LastModified)[-1].Key' --output text
Therefore (using shell syntax), you could use:
object=`aws s3api list-objects-v2 --bucket BUCKET-NAME --prefix data1/ --query 'sort_by(Contents, &LastModified)[-1].Key' --output text`
aws s3 cp s3://BUCKET-NAME/$object E:\Datafolder
You might need to tweak it to get it working on Windows.
Basically, it gets the bucket listing, sorts by LastModified, then grabs the name of the last object in the list.
Modified answer to work with Windows .bat file. Uses Windows cmd.exe
for /f "delims=" %%i in ('aws s3api list-objects-v2 --bucket BUCKET-NAME --prefix data1/ --query "sort_by(Contents, &LastModified)[-1].Key" --output text') do set object=%%i
aws s3 cp s3://BUCKET-NAME/%object% E:\Datafolder

Copy Data From AWS S3 Bucket Locally Based on Date of File

I want to copy the Latest CSV file which has the date appended from an AWS S3 bucket to a local drive.
I have the basic code that will download the file but it downloads all the files in the bucket I only want the file uploaded that day, latest file.
Download latest object by modified date
If you only wish to grab the file that was last stored on Amazon S3, you could use:
aws s3 cp s3://my-bucket/`aws s3api list-objects-v2 --bucket my-bucket --query 'sort_by(Contents, &LastModified)[-1].Key' --output text` .
This command does the following:
The inner aws s3api list-objects-v2 command lists the bucket, sorts by date (reversed), then returns the Key (filename) of the object that was last modified
The outer aws s3 cp command downloads that object to the local directory
Download latest object based on filename
If your filenames are like:
some_file_20190130.csv
some_file_20190131.csv
some_file_20190201.csv
then you can list by prefix and copy the last one:
aws s3 cp s3://my-bucket/`aws s3api list-objects-v2 --bucket my-bucket --prefix some_file_ --query 'sort_by(Contents, &Key)[-1].Key' --output text` .
This command does the following:
The inner aws s3api list-objects-v2 command lists the bucket, only shows files with a given prefix of some_file_, sorts by Key (reversed), then returns the Key (filename) of the object that is at the end of the sort
The outer aws s3 cp command downloads that object to the local directory

AWS CLI Download list of S3 files

We have ~400,000 files on a private S3 bucket that are inbound/outbound call recordings. The files have a certain pattern to it that lets me search for numbers both inbound and outbound. Note these calls are on the Glacier storage class
Using AWS CLI, I can search through this bucket and grep the files I need out. What I'd like to do is now initiate an S3 restore job to expedited retrieval (so ~1-5 minute recovery time), and then maybe 30 minutes later run a command to download the files.
My efforts so far:
aws s3 ls s3://exetel-logs/ --recursive | grep .*042222222.* | cut -c 32-
Retreives the key of about 200 files. I am unsure of how to proceed next, as aws s3 cp wont work for any objects in storage class.
Cheers,
The AWS CLI has two separate commands for S3: s3 ands3api. s3 is a high level abstraction with limited features, so for restoring files, you'll have to use one of the commands available with s3api:
aws s3api restore-object --bucket exetel-logs --key your-key
If you afterwards want to copy the files, but want to ensure to only copy files which were restored from Glacier, you can use the following code snippet:
for key in $(aws s3api list-objects-v2 --bucket exetel-logs --query "Contents[?StorageClass=='GLACIER'].[Key]" --output text); do
if [ $(aws s3api head-object --bucket exetel-logs --key ${key} --query "contains(Restore, 'ongoing-request=\"false\"')") == true ]; then
echo ${key}
fi
done
Have you considered using a high-level language wrapper for the AWS CLI? It will make these kinds of tasks easier to integrate into your workflows. I prefer the Python implementation (Boto 3). Here is example code for how to download all files from an S3 bucket.

AWS get-object doesn't create local directories

I am trying to download a file from S3 compatible storage and I am running the following command:
aws s3api get-object --endpoint-url https://my.endpoint.url/ --bucket my_bucket --key mailouts/m3/ma2.png mailouts/m3/ma2.png
And I get and error:
[Errno 2] No such file or directory: u'mailouts/m3/ma2.png'
However, when I run the following command:
aws s3api get-object --endpoint-url https://my.endpoint.url/ --bucket my_bucket --key mailouts/m3/ma2.png ma2.png
i do end up with ma2.png file in my current directory. So it looks like aws cli cannot create intermediate directories mailouts/m3
Is there a way to force aws cli to make local directories?
Not when retrieving a single file. The sync command in the AWS S3 CLI will create directories in the destination as long as there is at least one file in the directory. You can use the --include and --exclude options to narrow down the files synced (even down to just ma2.png) if you do not want to sync the entire directory tree.
S3 buckets do not have directories/folders. When you have something like:
mailouts/m3/ma2.png
that is just a filename in your S3 bucket. If you want to save ma2.png in ./mailouts/m3, you have to parse the object name and create the intermediate folders/directories yourself.
The best way is to use aws s3 cp command, it will create needed folders.

AWS S3 download and copy

We have a bucket in AWS S3 where backups from production are being copy to.
My task is to copy the most recent backup file from AWS S3 to the local sandbox SQL Server, then do the restore.
I have installed all of the AWS tools for windows on the local server. Credentials to connect to AWS S3 work, etc.
My local server can list all of the files in the AWS S3 bucket. I can successfully download a single file if I specifically name that file.
Here is an example of that working pulling the most recent copy from July 25, 2016.
aws s3 cp s3://mybucket/databasefile_20160725.zip E:\DBA
My goal is to have a copy script that only pulls the most recent file, which I won't know the name of. I want to schedule this.
Nothing I google or try is getting me the correct syntax to do this.
to retrieve the latest file in your bucket you can do the following
aws s3api list-objects --bucket "mybucket" |\
jq '.Contents | sort_by(.LastModified) | .[-1].Key' --raw-output
The first command will list the objects of your bucket in Json, the elements of the JSon are listed here
Then you want to sort the element from their last modified date, take the last element, and you want they Key (i.e. name of the file in bucket). Adding the --raw-output flag to stripe quotes from the key name
You can reuse that in script or pipe it with the s3 cp command like below
aws s3api list-objects --bucket "mybucket" |\
jq '.Contents | sort_by(.LastModified) | .[-1].Key' --raw-output |\
xargs -I {} aws s3 cp s3://mybucket/{} E:\DBA