如果cp文件只有在它不存在的情况下如何,否则抛出错误?

时间:2014-11-17 17:22:13

标签: amazon-web-services aws-cli

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

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

6 个答案:

答案 0 :(得分:28)

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

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

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


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

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

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

答案 1 :(得分: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)是 - 如果你正在使用完整路径,请包括... 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 -just-验证校验和,因为它似乎总是做多部分样式校验和..哦,也许一些--dryrun和一些输出抓取和同步.. )

答案 2 :(得分:3)

当且仅当列表成功时,您可以通过列出和复制来执行此操作。

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

修改:替换&&到||如果列表失败,具有所需的效果,请复制

答案 3 :(得分:0)

  

AWS HACK

如果文件已经存在,您可以运行以下命令来引发错误

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

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

OR

#!/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

答案 4 :(得分:0)

我投票赞成阿维吉亚诺。使用上面的示例,我可以在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

答案 5 :(得分:0)

您还可以通过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 document

  • 如果您对存储桶具有s3:ListBucket权限,Amazon S3将返回HTTP状态码404(“无此键”)错误。
  • 如果您没有s3:ListBucket权限,Amazon S3将返回HTTP状态码403(“访问被拒绝”)错误。