App-mvr

 view release on metacpan or  search on metacpan

lib/App/mvr.pm  view on Meta::CPAN

package App::mvr;
use v5.14.0;
use strict;
use warnings;
# ABSTRACT: like mv, but clever
our $VERSION = '0.005'; # VERSION

use Exporter qw(import);
our @EXPORT = qw(mvr);

use Path::Tiny 0.034;
use Try::Tiny;
use Carp;

our $VERBOSE = 0;


my $duplicates = sub {
    my $A = shift;
    my $B = shift;
    return if $A->stat->size != $B->stat->size; # avoid reading file off disk

    # Pull out the big guns
    return $A->digest eq $B->digest;
};

sub mvr {
    my %args = @_;
    $args{dest}   //= delete $args{destination};
    $args{source} = [delete $args{source}] unless ref $args{source} eq 'ARRAY';

    my $dest = path( $args{dest} );
    my $dest_is_dir = $dest->exists && $dest->is_dir;
    croak sprintf("target `%s' is not a directory\n", $dest)
        if @{ $args{source} } > 1 and !$dest_is_dir;

    STDOUT->autoflush(1) if $VERBOSE;
    foreach my $from ( map { path($_) } @{ $args{source} } ) {
        print "\r${from}\e[K" if $VERBOSE == 1;

        unless ($from->exists) {
            carp sprintf("Cannot stat `%s': No such file or directory\n", $from);
            next;
        }
        my $to = path( $dest, ($dest_is_dir ? $from->basename : ()) );
        croak sprintf("`%s' and `%s' are the same file\n", $to, $from)
            if $from->absolute eq $to->absolute;

        if ($to->exists) {
            if ($args{deduplicate}) {
                print STDERR "File already exists; checking for duplication..."
                    if $VERBOSE > 1;
                if ($duplicates->($from, $to)) {
                    printf STDERR
                        " `%s' and `%s' are duplicates; removing the source file.\n",
                        $from->basename, $to->basename
                        if $VERBOSE > 1;
                    $from->remove;
                    $to->touch;
                    next;
                }
                else {
                    printf STDERR
                        " `%s' and `%s' are not duplicates.\n",
                        $from->basename, $to->basename
                        if $VERBOSE > 1;
                }
            }

            my ($prefix, $suffix) = $to->basename =~ m{^(.*)\.(\w+)$};
            $to = Path::Tiny->tempfile(
                UNLINK => 0,



( run in 1.952 second using v1.01-cache-2.11-cpan-39bf76dae61 )