end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

Net::Amazon::S3 for perl で、aws s3にあるファイル一覧を取得

https://docs.aws.amazon.com/cli/latest/reference/s3api/list-objects.html

aws s3の仕様は↑こちらで、 これを Net::Amazon::S3 for perl で実装したものが、以下。

大量のファイルでもあっても取得できるポイントは、 perl src内にあるmarkとnext_maker で、 これがページングの役割を担っています。

#!/usr/local/bin/perl
use strict;
use warnings;
use Encode;
use Net::Amazon::S3;
use Data::Dumper;

my $CONF =
    {aws_s3=>
     {client=>{
               host=>                   'ないしょ',
               aws_access_key_id =>     'ないしょ',
               aws_secret_access_key => 'ないしょ',
               retry => 1},
      bucket=>'ないしょ'},
     
     ls=>{max_keys=>5,     # 一度に取得するobj keyの制限
          delimiter=>"/",  # 不要と思いますが、これがないとs3がis_truncatedを返さない...
          max_exec=>10,    # lsを実行する回数制限
          sleep=>2}        # やさしく ls
    };


main( @ARGV );

sub main {
    my ($kyoten_code) = @_;

    unless( $kyoten_code ){
        return disp_usage();
    }

    my $s3 = Net::Amazon::S3->new(%{$CONF->{aws_s3}->{client}});
    $s3->ua( LWP::UserAgent->new(ssl_opts=>{verify_hostname =>0}) );

    my $bucket = $s3->bucket($CONF->{aws_s3}->{bucket} );

    my $list_opt =
        {prefix=>    $kyoten_code,
         max_keys => $CONF->{ls}->{max_keys},
         delimiter=> $CONF->{ls}->{delimiter} };
    my $pre_ls_res = {is_truncated=>1};

    my $ls_exec_count = 0;
    my $obj_keys_size = 0;
    
    while($pre_ls_res->{is_truncated} and
          $ls_exec_count++ < $CONF->{ls}->{max_exec} ){

        # 前回の続きから、ls する為、markerをset
        $list_opt->{marker} = $pre_ls_res->{next_marker};

        my $ls_res = $bucket->list($list_opt);
        
        $obj_keys_size += scalar(@{$ls_res->{keys}});
        
        for my $obj_info ( @{$ls_res->{keys}} ){
            # version idは別途、取得する必要あり
            my $obj_detail = $bucket->head_key($obj_info->{key});
            
            my $disp_str = join("\t",
                                $obj_info->{key},
                                $obj_detail->{'x-amz-version-id'} || '',
                                $obj_info->{size},
                                $obj_info->{etag},
                                $obj_info->{last_modified});
            print "$disp_str\n";
        }

        # 続きがある場合、is_truncated = true ですって
        $pre_ls_res->{is_truncated} = $ls_res->{is_truncated};
        $pre_ls_res->{next_marker} = $ls_res->{next_marker};

        sleep($CONF->{ls}->{sleep});
    }

    print "You have $obj_keys_size objects !!\n";
}

sub disp_usage {
    print "Usage: $0 HEIM_KYOTEN_CODE.\n";
}


1;