App-BinPackUtils
view release on metacpan or search on metacpan
lib/App/BinPackUtils.pm view on Meta::CPAN
for my $item (@{ $args{items} }) {
if (ref $item eq 'ARRAY') {
$bp->add_item(label => $item->[0], size => $item->[1]);
} else {
my @item = split /\s*,\s*/, $item;
$bp->add_item(label => $item[0], size => $item[1]);
}
}
my @bins = $bp->pack_bins;
[200, "OK", $args{num_bins} ? scalar(@bins) : \@bins];
}
$SPEC{bin_files} = {
v => 1.1,
summary => 'Put files into bins of certain size (or number of items)',
args => {
%argopt_bin_size,
%argopt_bin_max_items,
bin_prefix => {
schema => 'filename*',
default => 'bin',
},
%arg0_files,
%argopt_dereference_files,
%argopt_move,
%argopt_num_bins,
},
args_rels => {
req_one => [qw/bin_size bin_max_items/],
},
deps => {
prog => 'du',
},
examples => [
{
summary => 'Put at most 100MB in each bin, move the files',
src => 'bin-files --bin-size 100MB --move *.jpg',
src_plang => 'bash',
test => 0,
'x.doc.show_result' => 0,
},
{
summary => 'Put at most 1000 files in each bin, move the files',
src => 'bin-files --bin-max-items 1000 --move *.jpg',
src_plang => 'bash',
test => 0,
'x.doc.show_result' => 0,
},
],
};
sub bin_files {
require String::ShellQuote;
my %args = @_;
my $bin_size = $args{bin_size};
my $bin_max_items = $args{bin_max_items};
my $bin_prefix = $args{bin_prefix} // "bin";
my @items;
for my $file (@{ $args{files} }) {
return [404, "File '$file' does not exist"] unless -e $file;
if (defined $bin_size) {
my $cmd = "du ".($args{dereference_files} ? "-D " : "")."--apparent-size -sb ".
String::ShellQuote::shell_quote($file);
my $out = `$cmd`;
my $size;
if ($out =~ /\A(\d+)/) {
$size = $1;
} else {
return [500, "Cannot find the size of '$file': $!"];
}
push @items, [$file, $size];
} else {
push @items, [$file, 1];
}
}
my $res = pack_bins(bin_size => $bin_size // $bin_max_items, items => \@items);
return $res unless $res->[0] == 200;
# reformat as a single 2D table
my @rows;
my $bin_num = 0;
my %bin_names;
for my $bin (@{ $res->[2] }) {
$bin_num++;
for my $item (@{ $bin->{items} }) {
my $bin_name = "$bin_prefix$bin_num";
$bin_names{$bin_name}++;
push @rows, {
bin => $bin_name,
file=>$item->{label},
size=>$item->{size},
};
}
}
if ($args{move}) {
# create all the directories for bins
for my $bin_name (sort keys %bin_names) {
return [412, "Directory $bin_name must not already exist"]
if -d $bin_name;
log_info "Creating directory $bin_name ...";
mkdir $bin_name or return [500, "Can't create directory $bin_name: $!"];
}
# move files to bins
for my $row (@rows) {
log_info "Moving '$row->{file}' to $row->{bin} ...";
rename($row->{file}, "$row->{bin}/$row->{file}") or do {
log_warn "Can't move '$row->{file}' to $row->{bin}/: $!, skipped";
};
}
}
[200, "OK", $args{num_bins} ? scalar(keys %bin_names) : \@rows];
}
$SPEC{bin_files_into_dvds} = {
v => 1.1,
summary => 'Put files into DVD bins',
( run in 2.609 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )