【问题标题】:PowerShell for AWS: List only "folders" from S3 bucket?适用于 AWS 的 PowerShell:仅列出 S3 存储桶中的“文件夹”?
【发布时间】:2021-12-04 04:12:22
【问题描述】:

是否有任何简单的方法可以使用 PowerShell 仅从 S3 存储桶中获取“文件夹”列表,而不列出每个对象,并且只编写不同路径的编译列表?我正在处理的存储桶中有数十万个单独的对象,这需要很长时间。

这可能是一个非常愚蠢的问题,如果是这种情况,我很抱歉,但我在 Google 或 SO 上找不到任何东西来回答这个问题。我尝试在 Get-S3Object 的 -KeyPrefix 和 -Key 参数中添加通配符,但无济于事。这是唯一一个似乎能够完成我所追求的事情的 cmdlet。

毫无意义的背景故事:我只是想确保将文件传输到正确的现有文件夹。我是签约的第三方,所以我没有控制台登录权限,也不是 AWS 账户的维护者。

我知道使用 Java 和 C# 和其他方法可以做到这一点,但我正在处理这个在 PS 中相当简单的项目所涉及的所有其他事情,并希望能够坚持下去。

提前致谢。

【问题讨论】:

    标签: powershell amazon-web-services amazon-s3 aws-powershell


    【解决方案1】:

    您可以使用AWS Tools For PowerShell 列出存储桶中的对象(通过Get-S3Object)并从响应对象中提取公共前缀。

    下面是一个递归检索子目录的小库:

    function Get-Subdirectories
    {
      param
      (
        [string] $BucketName,
        [string] $KeyPrefix,
        [bool] $Recurse
      )
    
      @(get-s3object -BucketName $BucketName -KeyPrefix $KeyPrefix -Delimiter '/') | Out-Null
    
      if($AWSHistory.LastCommand.Responses.Last.CommonPrefixes.Count -eq 0)
      {
        return
      }
    
      $AWSHistory.LastCommand.Responses.Last.CommonPrefixes
    
      if($Recurse)
      {
        $AWSHistory.LastCommand.Responses.Last.CommonPrefixes | % { Get-Subdirectories -BucketName $BucketName -KeyPrefix $_ -Recurse $Recurse }
      }
    }
    
    function Get-S3Directories
    {
      param
      (
        [string] $BucketName,
        [bool] $Recurse = $false
      )
    
      Get-Subdirectories -BucketName $BucketName -KeyPrefix '/' -Recurse $Recurse
    }
    

    此递归函数依赖于在每次迭代时更新 KeyPrefix 以检查传递给它的每个 KeyPrefix 中的子目录。通过将分隔符设置为'/',在第一次出现分隔符之前匹配 KeyPrefix 字符串的键将滚动到 $AWSHistory 的最后一个响应中的 CommonPrefixes 集合中。

    仅检索 S3 存储桶中的顶级目录:

    PS C:/> Get-S3Directories -BucketName 'myBucket'
    

    检索 S3 存储桶中的所有目录:

    PS C:/> Get-S3Directories -BucketName 'myBucket' -Recurse $true
    

    这将返回一个字符串集合,其中每个字符串都是一个公共前缀。

    示例输出:

    myprefix/
    myprefix/txt/
    myprefix/img/
    myotherprefix/
    ...
    

    【讨论】:

      【解决方案2】:
      $objects = Get-S3Object -BucketName $bucketname -ProfileName $profilename -Region $region
      $paths=@()
      foreach($object in $objects) 
      {
          $path = split-path $object.Key -Parent 
          $paths += $path
      }
      $paths = $paths | select -Unique
      write-host "`nNumber of folders "$paths.count""
      Write-host "$([string]::join("`n",$paths)) "
      

      【讨论】:

        【解决方案3】:

        此版本的 Powershell 在单个 S3 存储桶中迭代超过 1000 个键(aws 仅限制 API get-S3object 的 1000 个键,因此我们需要一个 while 循环来获取超过 1000 个键,即文件夹) 输出生成到 csv 后,记得在 Excel 中对重复项进行排序以删除重复项(PS,任何人都可以协助对重复项进行排序,因为我认为我的脚本不能很好地处理重复项)

        #Main-Code 
        $keysPerPage = 1000 #Set max key of AWS limit of 1000
        $bucketN = 'testBucket' #Bucketname
        $nextMarker = $null 
        $output =@()
        $Start = "S3 Bucket Name : $bucketN"
        $End = "- End of Folder List -"
        
        Do
        {
          #Iterate 1000 records per do-while loop, this is to overcome the limitation of only 1000 keys retrieval per get-s3object calls by AWS 
          $batch = get-s3object -BucketName $bucketN -Maxkey $keysPerPage -Marker $nextMarker 
        
          $batch2 = $batch.key | % {$_.Split('/')[0]} | Sort -Unique 
          $output += $batch2 
          $batch2
        
          $nextMarker= $AWSHistory.LastServiceResponse.NextMarker
        } while ($nextMarker)
        
           #Output to specific folder in a directory
           $Start | Out-file C:\Output-Result.csv  -Append
           $output | Out-file C:\Output-Result.csv  -Append
           $End | Out-file C:\Output-Result.csv -Append
        

        【讨论】:

          【解决方案4】:

          接受的答案是正确的,但有一个缺陷。如果您有一个包含许多“文件夹”(超过 1000 个)的大存储桶,您将只能使用以下方法获得最后 1000 个前缀:

          $AWSHistory.LastCommand.Responses.Last.CommonPrefixes
          

          AWS 以 1000 为增量对响应进行批处理。如果你看

          $AWSHistory.LastCommand.Responses.History 
          

          您将看到多个条目。不幸的是,默认情况下只有 5 个。 您可以使用 Set-AWSHistoryConfiguration 函数更改该行为。

          要增加历史响应的数量,请使用 -MaxServiceCallHistory 参数。

          Set-AWSHistoryConfiguration -MaxServiceCallHistory 20
          

          这将存储下一个(以及所有后续)命令的最后 20 个服务调用。

          通过上述配置,您可以从一个文件夹中检索多达 20000 个子文件夹。

          要检索所有文件夹,请执行以下操作:

          $subFolders = ($AwsHistory.LastCommand.Responses.History).CommonPrefixes
          

          注意:增加配置参数会占用更多内存。

          【讨论】:

            猜你喜欢
            • 2013-01-17
            • 2016-10-29
            • 2020-09-02
            • 2018-04-19
            • 2016-11-02
            • 1970-01-01
            • 2021-07-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多