34

I have aws cli installed. I'm just not sure how to do this in shell script.

when I run command aws s3 ls s3://bucket it would give me something like this

A client error (NoSuchBucket) occurred when calling the ListObjects operation: The specified bucket does not exist

That means the bucket doesn't exist. So I want to run that from shell script and check if grep finds it. But my command doesn't work.

if [ $(aws s3 ls "s3://$S3_BUCKET" | grep 'NoSuchBucket' &> /dev/null) == 0 ] 
then
    echo "$S3_BUCKET doesn\'t exist please check again"
    exit
fi

It just gave me this

backup.sh: 20: [: 0: unexpected operator

Updated

I changed the script to be

echo "S3_BUCKET=$S3_BUCKET"
if aws s3 ls "s3://$S3_BUCKET" | grep -q 'AllAccessDisabled'    
then
    echo "$S3_BUCKET doesn\'t exist please check again"
    exit
fi

And this is the output I got

A client error (AllAccessDisabled) occurred when calling the ListObjects operation: All access to this object has been disabled

So the text contains AllAccessDisabled but I still don't the echo the next line.

toy
  • 11,711
  • 24
  • 93
  • 176
  • Does this answer your question? [AWS S3: How to check if a file exists in a bucket using bash](https://stackoverflow.com/questions/41871948/aws-s3-how-to-check-if-a-file-exists-in-a-bucket-using-bash) – Amri Apr 28 '20 at 12:02

11 Answers11

51

The s3api head-bucket is more direct and does not incur the expense of listing a bucket with many files.

http://docs.aws.amazon.com/cli/latest/reference/s3api/head-bucket.html

if aws s3api head-bucket --bucket "$S3_BUCKET" 2>/dev/null; then
John Milton
  • 511
  • 1
  • 4
  • 2
  • 1
    No it shouldn't, because it doesn't work in the case that the bucket is owned by another user: http://pasted.co/7dae7402 – scubbo Nov 01 '17 at 06:23
  • 1
    Does this differentiate between a bucket that doesn't exist and a bucket that you don't have access to? – brianmearns Apr 12 '19 at 15:03
  • 1
    No, it doesn't. It will fail if the bucket does not exist as well as if it exists, but is owned by another user...just with different error messages. You need to inspect the error message. – Brooks Sep 29 '19 at 00:28
20

The code you listed wouldn't have given you that error.

If you had written the script without the space between the leading [ and the $( that would have.

Also grep isn't going to output 0 in that case so that test isn't going to work the way you want.

If you want to test whether grep found anything then you want to use the -q argument to grep like this:

if aws s3 ls "s3://$S3_BUCKET" 2>&1 | grep -q 'NoSuchBucket'
then
Etan Reisner
  • 77,877
  • 8
  • 106
  • 148
  • 1
    That's error output. That's probably going to standard error and not standard output. You need to redirect for that. See updated code. – Etan Reisner Jun 26 '15 at 16:24
17

I know this is an old question, but I came here for some answers and using some existing answers and some experimentations of my own came up with a script which handles different return values:

bucketstatus=$(aws s3api head-bucket --bucket "${s3_bucket}" 2>&1)
if echo "${bucketstatus}" | grep 'Not Found';
then
  echo "bucket doesn't exist";
elif echo "${bucketstatus}" | grep 'Forbidden';
then
  echo "Bucket exists but not owned"
elif echo "${bucketstatus}" | grep 'Bad Request';
then
  echo "Bucket name specified is less than 3 or greater than 63 characters"
else
  echo "Bucket owned and exists";
fi
ErikE
  • 48,881
  • 23
  • 151
  • 196
Biplob Biswas
  • 1,761
  • 19
  • 33
5

Here's how I did it, the other answer will say there is a bucket if there is an AWS error that doesn't contain 'NoSuchBucket' such as token expiry

echo "Checking S3 bucket exists..."                                                                                                                                                                                                           
BUCKET_EXISTS=true                                                                                                                                                                                                                            
S3_CHECK=$(aws s3 ls "s3://${BUCKET_NAME}" 2>&1)                                                                                                                                                 

#Some sort of error happened with s3 check                                                                                                                                                                                                    
if [ $? != 0 ]                                                                                                                                                                                                                                
then                                                                                                                                                                                                                                          
  NO_BUCKET_CHECK=$(echo $S3_CHECK | grep -c 'NoSuchBucket')                                                                                                                                                                                     
  if [ $NO_BUCKET_CHECK = 1 ]; then                                                                                                                                                                                                              
    echo "Bucket does not exist"                                                                                                                                                                                                              
    BUCKET_EXISTS=false                                                                                                                                                                                                                       
  else                                                                                                                                                                                                                                        
    echo "Error checking S3 Bucket"                                                                                                                                                                                                           
    echo "$S3_CHECK"                                                                                                                                                                                                                          
    exit 1                                                                                                                                                                                                                                    
  fi 
else                                                                                                                                                                                                                                         
  echo "Bucket exists"
fi                                                                                                                                                                                                                                            
danelips
  • 774
  • 6
  • 5
5

The way recommended by aws is aws s3api head-bucket --bucket $S3_BUCKET See https://docs.aws.amazon.com/cli/latest/reference/s3api/head-bucket.html

Vincent
  • 391
  • 3
  • 10
3

I stumbled upon this question, and would like to add the solution using the AWS recommended way using head-bucket.

BUCKET_EXISTS=$(aws s3api head-bucket --bucket <bucket_name> 2>&1 || true)
if [ -z "$BUCKET_EXISTS" ]; then
  echo "Bucket exists"
else
  echo "Bucket does not exist"
fi
Mornor
  • 3,471
  • 8
  • 31
  • 69
3

Without havent to handle errors:

if [[ ! -z $(aws s3api list-buckets --query 'Buckets[?Name==`bucket-name`]' --output text) ]]; then
  echo "Bucket Exists"
fi
Christian
  • 3,708
  • 3
  • 39
  • 60
2
#!/bin/bash

if [[ -z $(aws s3api head-bucket --bucket my-bucket 2>&1) ]]; then
        echo "bucket exists"
else
        echo "bucket does not exist or permission is not there to view it."
fi
Yogesh Gupta
  • 1,226
  • 1
  • 12
  • 23
0

this might me simplest approach

if aws s3 ls "s3://$S3_BUCKET" 2>&1 | grep -q 'An error occurred'
then
    echo "bucket does not exist or permission error."
else
    echo "bucket exist"
fi
choasia
  • 10,404
  • 6
  • 40
  • 61
vinay
  • 1,004
  • 1
  • 11
  • 27
0

A nice one liner that builds off John Milton's anser:

bucket_exists=$(aws s3api head-bucket --bucket $bucket_name 2>/dev/null && echo "yes" || echo "no")

A successful response will return a 0 status from the aws command and run the first part of the ternary.

A failed response will return a 254 status from the aws command and run the latter part of the ternary.

IMHO this is a lot easier to read, but to each their own.

domdambrogia
  • 2,054
  • 24
  • 31
0
aws s3 ls "s3://$S3_BUCKET" 2>&1 || aws s3api create-bucket --bucket $S3_BUCKET --region us-east-1 --no-cli-pager

This worked good for me as one line command.

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/34653861) – ryanwebjackson Jul 14 '23 at 02:13