App-BoolFindGrep

 view release on metacpan or  search on metacpan

bin/bfg  view on Meta::CPAN

use Getopt::Long qw(:config no_ignore_case auto_version);
use Pod::Find qw(pod_where);
use Pod::Usage;
use App::BoolFindGrep::CLI;

our $VERSION = '0.06'; # VERSION

my %opt;
#<<<
my $result = GetOptions(
    q(--files-from|T=s)       => sub { $opt{ $_[0] } = $_[1] },
    q(--files-delim|d=s)      => sub { $opt{ $_[0] } = $_[1] },
    q(--file-expr|f=s{1,})    => sub { push @{ $opt{ $_[0] } }, $_[1] },
    q(--find-type|t=s)        => sub { $opt{ $_[0] } = $_[1] },
    q(--find-ignore-case|I)   => sub { $opt{ $_[0] } = $_[1] },
    q(--directory|D=s{1,})    => sub { push @{ $opt{ $_[0] } }, $_[1] },
    q(--fixed-strings|F)      => sub { $opt{ $_[0] } = $_[1] },
    q(--match-expr|m=s{1,})   => sub { push @{ $opt{ $_[0] } }, $_[1] },
    q(--ignore-case|i)        => sub { $opt{ $_[0] } = $_[1] },
    q(--line-regexp|x)        => sub { $opt{ $_[0] } = $_[1] },
    q(--word-regexp|w)        => sub { $opt{ $_[0] } = $_[1] },
    q(--glob-regexp|g)        => sub { $opt{ $_[0] } = $_[1] },
    q(--files-with-matches|l) => sub { $opt{ $_[0] } = $_[1] },
    q(--slash-as-delim|s)     => sub { $opt{ $_[0] } = $_[1] },
    q(usage|help|h)           => sub { pod2usage( q(-verbose) => 1 ) },
    q(man)                    => sub { pod2usage( q(-verbose) => 2 ) },
);
#>>>

if (@ARGV) {
    say qq(Unparsed options: '@ARGV');
    pod2usage( -verbose => 1 );
}

pod2usage( -verbose => 1 ) if !($result) || !(%opt);

my $obj   = App::BoolFindGrep::CLI->new();
my $check = $obj->args_checker(%opt);

exit 1 unless $check;
exit 1 unless $obj->process();

my @result = @{ $obj->result() };

say for @result;

=pod

=encoding utf8

=head1 NAME

bfg - find and grep files using boolean expressions.

=head1 VERSION

version 0.06

=head1 DESCRIPTION

This program combines the power of three Unix tools (in their GNU versions): bool, find and grep to provide a way to search by filenames and/or by file contents using boolean expressions. Internaly, all boolean expressions with regexps/strings are tr...

Complex searches using B<grep> are very painful and B<bool> have lots of limitations and complex escape rules. B<bfg> simplify these searches by using more clear syntax and better performance in some cases.

For example, to search

    first AND second AND third AND fourth AND NOT fifth

in filenames, and the same expression in file contents using B<find> and B<grep>, you need do:

    find . \
	-type f \
	-name '*first*' -a \
	-name '*second*' -a \
	-name '*third*' -a \
	-name '*fourth*' -a \
	-not -name '*fifth*' \
	-print0 |
    xargs grep -F -l 'first' |
    tr '\n' |
    xargs grep -F -l 'second' |
    tr '\n' |
    xargs grep -F -l 'third' |
    tr '\n' |
    xargs grep -F -l 'fourth' |
    tr '\n' |
    xargs grep -F -l -v 'fifth'

Using B<bfg> you can sumarize this to:

    bfg -t literal -f \
    first AND second AND third AND fourth AND NOT fifth \
    -F -m \
    first AND second AND third AND fourth AND NOT fifth

=head2 About Boolean Expressions

In the context of this program, a B<Boolean Expression> is a composite of I<OPERANDS>, I<OPERATORS> and I<GROUPS>.

An I<OPERAND> is a string representing a literal text or a regular expression. It can be delimited by slashes like B<ed>, B<sed> or B<vim>.

An I<OPERATOR> can be B<AND>, B<OR> or B<NOT>, delimited by white spaces. The following composition of operators are valid too: B<AND NOT>, B<OR NOT>, B<NOT NOT NOT> ...  Operators are case insensitive.

A I<GROUP> is a sub expression delimite by parentheses used to define a set of sub conditions to match.

Any expression valid in program languages are valid here.

=head1 USAGE

    bfg [ -m <EXPR>]
    bfg [-F|-i|[-w|-x]] [-m <EXPR>]
    bfg [-D <DIR1 [DIR2 [DIR3]]>] [-t <literal|glob|regexp>] [-I <0|1>] -f <EXPR>
    bfg [-t <literal|glob|regexp>] [-I <0|1>] -f <EXPR> -m <EXPR>
    bfg [-T <filename|-|STDIN> [-d <char>]] [-F|-i|[-w|-x]] -m <EXPR>

    OPTIONS:
    [ --files-from         | -T ]    file name, "-" or stdin.
    [ --files-delim        | -d ]    file names' character separator.
    [ --file-expr          | -f ]    boolean expr to file names.
    [ --find-type          | -t ]    regexp (default), literal or glob.
    [ --find-ignore-case   | -I ]    ignore find operands' case.



( run in 2.325 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )