38
aws s3 cp "dist/myfile" "s3://my-bucket/production/myfile"

它总是复制myfile到 s3 - 如果文件不存在,我只想复制文件,否则抛出错误。我该怎么做?或者至少我如何使用 awscli 检查文件是否存在?

4

7 回答 7

54

您可以通过列出文件并查看它是否返回某些内容来测试文件是否存在。例如:

aws s3 ls s3://bucket/file.txt | wc -l

如果文件不存在,这将返回零(无行)。


如果您只想复制存在的文件,请尝试sync命令,例如:

aws s3 sync . s3://bucket/ --exclude '*' --include 'file.txt'

这将使本地文件与远程对象同步,仅当它不存在或本地文件与远程对象不同时才复制它。

于 2014-11-18T20:14:53.573 回答
10

所以,事实证明“aws s3 sync”不做文件,只做目录。如果你给它一个文件,你会得到……有趣的……行为,因为它把你给它的任何东西都当作一个目录,并在上面加上一个斜线。至少 aws-cli/1.6.7 Python/2.7.5 Darwin/13.4.0 可以。

    %% date > test.txt
    %% aws s3 sync test.txt s3://bucket/test.txt
    warning: Skipping file /Users/draistrick/aws/test.txt/. File does not exist.

因此,如果您 - 真的 - 只想同步文件(仅在存在且校验和匹配时上传),您可以这样做:

    file="test.txt"
    aws s3 sync --exclude '*' --include "$file" "$(dirname $file)" "s3://bucket/"

请注意排除/包含顺序 - 如果您反转它,它将不包含任何内容。并且您的源和包含路径需要在匹配时保持理智,因此如果您使用完整路径,则可能需要 $(basename $file) 用于 --include ... aws --debug s3 sync 是您的朋友看看包含如何评估。

并且不要忘记目标是目录键,而不是文件键。

这是一个工作示例:

  %% file="test.txt"
  %% date >> $file
  %% aws s3 sync --exclude '*' --include "$file" "$(dirname $file)" "s3://bucket/"
  upload: ./test.txt to s3://bucket/test.txt/test.txt
  %% aws s3 sync --exclude '*' --include "$file" "$(dirname $file)" "s3://bucket/"
  %% date >> $file
  %% aws s3 sync --exclude '*' --include "$file" "$(dirname $file)" "s3://bucket/"
  upload: ./test.txt to s3://bucket/test.txt/test.txt

(现在,如果有一种方法可以让 aws s3 验证校验和,因为它似乎总是做多部分样式校验和.. 哦,也许一些 --dryrun 和一些输出抓取和同步..)

于 2015-04-21T20:49:59.610 回答
6

当且仅当列表成功时,您可以通过列出和复制来做到这一点。

aws s3 ls "s3://my-bucket/production/myfile" || aws s3 cp "dist/myfile" "s3://my-bucket/production/myfile"

编辑:将 && 替换为 || 如果列表失败,请复制所需的效果

于 2015-07-09T23:28:06.357 回答
2

您还可以通过子命令检查文件是否存在aws s3api head-object。这样做的一个优点aws s3 ls是它只需要s3:GetObject权限而不是s3:ListBucket.

$ aws s3api head-object --bucket ${BUCKET} --key ${EXISTENT_KEY}
{
    "AcceptRanges": "bytes",
    "LastModified": "Wed, 1 Jan 2020 00:00:00 GMT",
    "ContentLength": 10,
    "ETag": "\"...\"",
    "VersionId": "...",
    "ContentType": "binary/octet-stream",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}
$ echo $?
0

$ aws s3api head-object --bucket ${BUCKET} --key ${NON_EXISTENT_KEY}

An error occurred (403) when calling the HeadObject operation: Forbidden
$ echo $?
255

请注意,不存在对象的 HTTP 状态码取决于您是否拥有s3:ListObject权限。有关详细信息,请参阅API 文档:

  • 如果您拥有s3:ListBucket存储桶的权限,Amazon S3 将返回 HTTP 状态代码 404(“没有这样的键”)错误。
  • 如果您没有s3:ListBucket权限,Amazon S3 会返回 HTTP 状态代码 403(“拒绝访问”)错误。
于 2020-10-22T07:38:58.750 回答
0

AWS黑客

如果文件已存在,您可以运行以下命令以引发 ERROR

  • 运行 aws s3 sync 命令将文件同步到 s3,如果文件不存在,它将返回复制的路径,如果它退出,它将给出空白输出
  • 运行wc -c命令检查字符数并在输出为零时引发错误

com=$(aws s3 sync dist/s3://my-bucket/production/ | wc -c);if [[ $com -ne 0 ]]; 然后退出1;否则退出0;菲;

或者

#!/usr/bin/env bash
com=$(aws s3 sync dist s3://my-bucket/production/ | wc -c)
echo "hello $com"
if [[ $com -ne 0 ]]; then
echo "File already exists"
exit 1
else
echo "success"
exit 0
fi
于 2019-08-14T12:22:52.387 回答
0

我投票赞成aviggiano。使用他上面的例子,我可以让它在我的 windows .bat 文件中工作。如果 S3 路径存在,它将引发错误并结束批处理作业。如果文件不存在,它将继续执行复制功能。希望这对某人有所帮助。

:Step1

aws s3 ls s3://00000000000-fake-bucket/my/s3/path/inbound/test.txt && ECHO Could not copy to S3 bucket becasue S3 Object already exists, ending script. && GOTO :Failure

ECHO No file found in bucket, begin upload.

aws s3 cp Z:\MY\LOCAL\PATH\test.txt s3://00000000000-fake-bucket/my/s3/path/inbound/test.txt --exclude "*" --include "*.txt"


:Step2

ECHO YOU MADE IT, LET'S CELEBRATE

IF %ERRORLEVEL% == 0 GOTO :Success
GOTO :Failure

:Success
echo Job Endedsuccess
GOTO :ExitScript

:Failure
echo BC_Script_Execution_Complete Failure
GOTO :ExitScript

:ExitScript
于 2020-04-15T18:41:47.787 回答
0

我在 Windows 上运行 AWS。这是我的简单脚本。

rem 清理工作文件:

if exist  SomeFileGroup_remote.txt del /q SomeFileGroup_remote.txt
if exist  SomeFileGroup_remote-fileOnly.txt del /q SomeFileGroup_remote-fileOnly.txt
if exist  SomeFileGroup_Local-fileOnly.txt del /q SomeFileGroup_Local-fileOnly.txt
if exist  SomeFileGroup_remote-Download-fileOnly.txt del /q SomeFileGroup_remote-Download-fileOnly.txt

雷姆准备:

call F:\Utilities\BIN\mhedate.cmd
aws s3 ls s3://awsbucket//someuser@domain.com/BulkRecDocImg/folder/folder2/ --recursive >>SomeFileGroup_remote.txt
for /F "tokens=1,2,3,4* delims= " %%i in (SomeFileGroup_remote.txt) do @echo %%~nxl >>SomeFileGroup_remote-fileOnly.txt
dir /b temp\*.* >>SomeFileGroup_Local-fileOnly.txt
findstr  /v /I /l /G:"SomeFileGroup_Local-fileOnly.txt" SomeFileGroup_remote-fileOnly.txt >>SomeFileGroup_remote-Download-fileOnly.txt

雷姆下载:

for /F "tokens=1* delims= " %%i in (SomeFileGroup_remote-Download-fileOnly.txt) do (aws s3 cp s3://awsbucket//someuser@domain.com/BulkRecDocImg/folder/folder2/%%~nxi "temp" >>"SomeFileGroup_Download_%DATE.YEAR%%DATE.MONTH%%DATE.DAY%.log")
于 2021-08-14T03:09:57.313 回答