Skip to content

Commit 9a03ab6

Browse files
Merge pull request #963 from zirkelc/fix-s3-download
fix(amazon-s3-download): handle file, folder and bucket downloads
2 parents ce1a19b + b40f0b5 commit 9a03ab6

File tree

1 file changed

+80
-34
lines changed

1 file changed

+80
-34
lines changed

commands/developer-utils/aws/amazon-s3-download.sh

+80-34
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
# Documentation:
1313
# @raycast.description Download from Amazon S3 via URL
14-
# @raycast.argument1 { "type": "text", "placeholder": "S3 URL" }
14+
# @raycast.argument1 { "type": "text", "placeholder": "s3://bucket/key" }
1515
# @raycast.author Chris Cook
1616
# @raycast.authorURL https://github.com/zirkelc
1717

@@ -26,64 +26,110 @@ fi
2626

2727
# Try matching different S3 URL patterns
2828
# https://dev.to/aws-builders/format-and-parse-amazon-s3-url-5e10
29-
if [[ $URL =~ ^https?://s3\.([a-z0-9-]+)\.amazonaws\.com/([^/]+)/(.*)$ ]]; then
29+
if [[ $URL =~ ^https?://s3\.([a-z0-9-]+)\.amazonaws\.com/([^/]+)(/(.*))?$ ]]; then
3030
# Regional hostname with path-style
31+
# Example: https://s3.us-east-1.amazonaws.com/bucket/key
3132
BUCKET="${BASH_REMATCH[2]}"
32-
KEY="${BASH_REMATCH[3]}"
33-
elif [[ $URL =~ ^https?://([^/]+)\.s3\.([a-z0-9-]+)\.amazonaws\.com/(.*)$ ]]; then
33+
KEY="${BASH_REMATCH[4]}"
34+
elif [[ $URL =~ ^https?://([^/]+)\.s3\.([a-z0-9-]+)\.amazonaws\.com(/(.*))?$ ]]; then
3435
# Regional hostname with virtual-hosted-style
36+
# Example: https://bucket.s3.us-east-1.amazonaws.com/key
3537
BUCKET="${BASH_REMATCH[1]}"
36-
KEY="${BASH_REMATCH[3]}"
37-
elif [[ $URL =~ ^https?://s3\.amazonaws\.com/([^/]+)/(.*)$ ]]; then
38+
KEY="${BASH_REMATCH[4]}"
39+
elif [[ $URL =~ ^https?://s3\.amazonaws\.com/([^/]+)(/(.*))?$ ]]; then
3840
# Legacy hostname with path-style
41+
# Example: https://s3.amazonaws.com/bucket/key
3942
BUCKET="${BASH_REMATCH[1]}"
40-
KEY="${BASH_REMATCH[2]}"
41-
elif [[ $URL =~ ^https?://([^/]+)\.s3\.amazonaws\.com/(.*)$ ]]; then
43+
KEY="${BASH_REMATCH[3]}"
44+
elif [[ $URL =~ ^https?://([^/]+)\.s3\.amazonaws\.com(/(.*))?$ ]]; then
4245
# Legacy hostname with virtual-hosted-style
46+
# Example: https://bucket.s3.amazonaws.com/key
4347
BUCKET="${BASH_REMATCH[1]}"
44-
KEY="${BASH_REMATCH[2]}"
45-
elif [[ $URL =~ ^s3://([^/]+)/(.*)$ ]]; then
48+
KEY="${BASH_REMATCH[3]}"
49+
elif [[ $URL =~ ^s3://([^/]+)(/(.*))?$ ]]; then
4650
# S3 URI
51+
# Example: s3://bucket/key
4752
BUCKET="${BASH_REMATCH[1]}"
48-
KEY="${BASH_REMATCH[2]}"
53+
KEY="${BASH_REMATCH[3]}"
4954
else
5055
echo "Invalid URL: $URL"
5156
echo "URL must match recognized S3 patterns."
57+
echo "Patterns:"
58+
echo "- Global S3 URI: s3://bucket/key"
59+
echo "- Regional Path-Style URL: https://s3.region.amazonaws.com/bucket/key"
60+
echo "- Regional Virtual-Hosted-Style URL: https://bucket.s3.region.amazonaws.com/key"
61+
echo "- Legacy Path-Style URL: https://s3.amazonaws.com/bucket/key"
62+
echo "- Legacy Virtual-Hosted-Style URL: https://bucket.s3.amazonaws.com/key"
5263
exit 1
5364
fi
5465

55-
# Check for empty bucket or key
56-
if [[ -z "$BUCKET" || -z "$KEY" ]]; then
57-
echo "Error extracting bucket and key from URL: $URL"
58-
exit 1
59-
fi
66+
# Trim leading slash from KEY if present
67+
KEY="${KEY#/}"
6068

61-
# Remove trailing slash if present and set recursive download flag
62-
RECURSIVE=""
63-
if [[ "$KEY" =~ .*/$ ]]; then
64-
KEY="${KEY%/}" # Remove trailing slash for directory key
65-
RECURSIVE="--recursive"
69+
# Check for empty bucket
70+
if [[ -z "$BUCKET" ]]; then
71+
echo "Error extracting bucket from URL: $URL"
72+
exit 1
6673
fi
6774

68-
# Set download path
6975
DOWNLOAD_FOLDER="$HOME/Downloads"
70-
DOWNLOAD_PATH="$DOWNLOAD_FOLDER/$KEY"
7176

72-
if [[ -n "$RECURSIVE" ]]; then
73-
echo "Downloading directory $URL to $DOWNLOAD_PATH..."
74-
else
75-
echo "Downloading file $URL to $DOWNLOAD_PATH..."
77+
# Ensure download folder exists
78+
if [ ! -d "$DOWNLOAD_FOLDER" ]; then
79+
echo "Download folder does not exist"
80+
exit 1
7681
fi
7782

7883
# Print bucket and key
7984
echo "Bucket: $BUCKET"
80-
echo "Key: $KEY"
85+
echo "Key: ${KEY:-<entire bucket>}"
86+
echo "Download: $DOWNLOAD_FOLDER"
87+
echo ""
8188

82-
# Use recursive if necessary
83-
if aws s3 cp "s3://$BUCKET/$KEY" "$DOWNLOAD_PATH" $RECURSIVE; then
84-
echo "Downloaded successfully."
85-
open "$DOWNLOAD_FOLDER"
89+
if [ -z "$KEY" ]; then
90+
# No key provided, download entire bucket
91+
DOWNLOAD_PATH="$DOWNLOAD_FOLDER/$BUCKET"
92+
echo "Downloading entire bucket s3://$BUCKET to $DOWNLOAD_PATH..."
93+
RECURSIVE="--recursive"
8694
else
87-
echo "Download failed."
88-
exit 1
95+
# Check if the key ends with a slash, indicating it's likely a directory
96+
if [[ "$KEY" == */ ]]; then
97+
DOWNLOAD_PATH="$DOWNLOAD_FOLDER/$BUCKET/$KEY"
98+
echo "Downloading directory s3://$BUCKET/$KEY to $DOWNLOAD_PATH..."
99+
RECURSIVE="--recursive"
100+
else
101+
# Check if the object exists as a file
102+
if aws s3api head-object --bucket "$BUCKET" --key "$KEY" &>/dev/null; then
103+
# It's a file
104+
FILENAME=$(basename "$KEY")
105+
DOWNLOAD_PATH="$DOWNLOAD_FOLDER/$FILENAME"
106+
echo "Downloading file s3://$BUCKET/$KEY to $DOWNLOAD_PATH..."
107+
RECURSIVE=""
108+
else
109+
# It might be a directory without a trailing slash or it doesn't exist
110+
# Try to list objects with this prefix
111+
if aws s3api list-objects-v2 --bucket "$BUCKET" --prefix "$KEY/" --max-items 1 --query 'Contents[0].Key' --output text &>/dev/null; then
112+
# It's a directory
113+
DOWNLOAD_PATH="$DOWNLOAD_FOLDER/$BUCKET/$KEY"
114+
echo "Downloading directory s3://$BUCKET/$KEY to $DOWNLOAD_PATH..."
115+
RECURSIVE="--recursive"
116+
else
117+
echo "Error: No file or directory found at s3://$BUCKET/$KEY"
118+
exit 1
119+
fi
120+
fi
121+
fi
122+
fi
123+
124+
# Perform the download
125+
if aws s3 cp "s3://$BUCKET/${KEY:+$KEY}" "$DOWNLOAD_PATH" $RECURSIVE; then
126+
echo "Downloaded successfully."
127+
if [[ -n "$RECURSIVE" ]]; then
128+
open "$DOWNLOAD_FOLDER/$BUCKET"
129+
else
130+
open "$DOWNLOAD_FOLDER"
131+
fi
132+
else
133+
echo "Download failed. Error code: $?"
134+
exit 1
89135
fi

0 commit comments

Comments
 (0)