Question

I'm currently working with Amazon S3 and I am writing a program that uses the modified dates. I'm looking for a way to edit the modified dates.

I could loop trough all the files and save them as they are, but this sounds like a bad solution.

In PHP there is this function touch().

Does anyone know a solution, or has the same problem?

Was it helpful?

Solution

In response to @Daniel Golden's comment on @tkotisis answer. It looks like at least the AWS CLI tools do not let you copy an item on to itself. You can however 'force' a copy by updating the metadata.

$ aws s3 cp --metadata '{"touched":"now"}' s3://path/to/object s3://path/to/object

This recreates the object (downloads to the caller and reuploads it) replacing its content, owner and metadata. This will also trigger any attached Lambda events.

OTHER TIPS

You can achieve the same through a copy object request, specifying the CopySource to be same as the target key.

In essence, this will issue a PUT Object - COPY request to S3 with the corresponding source and target bucket/key.

Here is another whay to upload a null (or o Byte) file to S3. I verified this works You can also use the S3 API to upload a file with no body, like so:

aws s3api put-object --bucket "myBucketName" --key "dir-1/my_null_file"

Normally you would specify a --body blob, but its option and will just add the key as expected. See more on S3 API put-object

The version of AWS CLI tested with is: aws-cli/2.0.4 Python/3.7.5 Windows/10 botocore/2.0.0dev8

Here's how I did it in PHP (even works in outdated 5.4, had to go way back):

// Init an S3Client
$awsConfig = $app->config('aws');
$aws       = Aws::factory($awsConfig);
$s3Bucket  = $app->config('S3_Bucket');
$s3Client  = $aws->get('s3');

// Set null/empty file.
$result = $s3Client->putObject([
    'Bucket' => $s3Bucket,
    'Key' => "dir-1/my_null_file",
    'Body' => '',
    'ServerSideEncryption' => 'AES256',
]);

I find myself performing the copy trick pretty often when testing, to the extent that I've added a handy function to my .bashrc:

s3-touch() {
  aws s3 cp \
    --metadata 'touched=touched' \
    --recursive --exclude="*" \
    --include="$2" \
    "${@:3}" \
    "$1" "$1"
}

Example usage:

# will do a dryrun on a copy operation
s3-touch s3://bucket/prefix/ "20200311*" --dryrun

# the real thing, creating events for all objects
# in s3://bucket/prefix/ that start with 20200311
s3-touch s3://bucket/prefix/ "20200311*"

I'm doing this mainly for the S3-events that I want to trigger.

Following @g-io answer that simplified my day, here is another version of the same that makes it easy to touch a single file

s3-touch-single() {
  aws s3 cp \
    --metadata 'touched=touched' \
    "${@:3}" \
    "$1" "$1"
}

for example, looping an array of files we need to touch:

paths=("mydir/image.png" "mydir2/image2.png")
for i in "${paths[@]}"; do s3-touch-single "s3://my-bucket/$i"; done

check out https://github.com/emdgroup/awscli-s3touch

It's a plugin to the AWS CLI that adds a touch command.

Usage:

aws s3 touch my-bucket --prefix myfolder/

It works by reading the events attached to the bucket and simulating them client side.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top