App-finddo

 view release on metacpan or  search on metacpan

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

            schema => 'bool*',
        },
        # XXX add arg: doc/ebook, backup, compressed, archive

        # XXX add arg: recursive (-r)
        # XXX add arg: max_depth
        # XXX add arg: (mtime, ctime) (min, max)
        # XXX add arg: size (min, max)
    },
    args_rels => {
        'choose_one&' => [
            [qw/sort newest oldest smallest largest/],
            [qw/files dirs/],
            [qw/media audio video image/],
        ],
    },
    result_naked => 1,
    links => [
        {url=>'prog:find', summary => 'Unix command'},
    ],
};
sub finddo {
    my %args = @_;

    my $max_result = $args{max_result};
    if ($args{newest} || $args{oldest} || $args{largest} || $args{smallest}) {
        $max_result = 1 unless defined $max_result;
    }
    $max_result = -1 unless defined $max_result;

    my $re_ext;
    my $ext_cond;
    if (defined $args{media}) {
        $ext_cond = $args{media};
        $re_ext = _get_ext_re_from_mime_types_file(qr!^(?:audio|video|image)/!);
    } elsif (defined $args{audio}) {
        $ext_cond = $args{audio};
        $re_ext = _get_ext_re_from_mime_types_file(qr!^(?:audio)/!);
    } elsif (defined $args{video}) {
        $ext_cond = $args{video};
        $re_ext = _get_ext_re_from_mime_types_file(qr!^(?:video)/!);
    } elsif (defined $args{image}) {
        $ext_cond = $args{image};
        $re_ext = _get_ext_re_from_mime_types_file(qr!^(?:image)/!);
    }

    my @res;
  FIND:
    {
        opendir my $dh, "." or do {
            warn "finddo: Can't opendir: $!\n";
            last FIND;
        };
        my @entries = readdir $dh;
        closedir $dh;

      ENTRY:
        for my $entry (@entries) {
            next if $entry eq '.' || $entry eq '..';
            my @lst = lstat $entry;
            my @st  = $lst[2] & S_IFLNK ? stat($entry) : @lst;

            if (defined $args{exists}) {
                next ENTRY if $args{exists} xor @st;
            }
            if (defined $args{files}) {
                next ENTRY unless @st;
                next ENTRY if $st[2] & S_IFREG xor $args{files};
            }
            if (defined $args{dirs}) {
                next ENTRY unless @st;
                next ENTRY if $st[2] & S_IFDIR xor $args{dirs};
            }
            if ($re_ext) {
                my $match = $entry =~ $re_ext;
                $match = !$match unless $ext_cond;
                next ENTRY unless $match;
            }
            push @res, {name=>$entry, stat=>\@st};
        }

      SORT:
        {
            my $sort = $args{sort};
            if    ($sort)           { }
            elsif ($args{newest})   { $sort = "-mtime" }
            elsif ($args{oldest})   { $sort =  "mtime" }
            elsif ($args{largest})  { $sort = "-size"  }
            elsif ($args{smallest}) { $sort =  "size"  }
            last unless $sort;

            my $sortsub;
            if    ($sort eq   'name') { $sortsub = sub { $a->{name} cmp $b->{name} } }
            elsif ($sort eq  '-name') { $sortsub = sub { $b->{name} cmp $a->{name} } }
            elsif ($sort eq  'mtime') { $sortsub = sub { ($a->{stat}[9]||0) <=> ($b->{stat}[9]||0) } }
            elsif ($sort eq '-mtime') { $sortsub = sub { ($b->{stat}[9]||0) <=> ($a->{stat}[9]||0) } }
            elsif ($sort eq   'size') { $sortsub = sub { ($a->{stat}[7]||0) <=> ($b->{stat}[7]||0) } }
            elsif ($sort eq  '-size') { $sortsub = sub { ($b->{stat}[7]||0) <=> ($a->{stat}[7]||0) } }

            @res = sort $sortsub @res;
        }

        @res = map {$_->{name}} @res;

      LIMIT:
        {
            last unless $max_result >= 0;
            if (@res > $max_result) {
                splice @res, $max_result;
            }
        }

    }

    if ($args{command} && @{$args{command}}) {
        if (@res) {
            system {$args{command}[0]} @{$args{command}}, @res;
            exit $?;
        } else {
            warn "finddo: No matching files\n";
            exit 1;



( run in 1.902 second using v1.01-cache-2.11-cpan-99c4e6809bf )