App-CSVUtils

 view release on metacpan or  search on metacpan

lib/App/CSVUtils/csv_cmp.pm  view on Meta::CPAN

package App::CSVUtils::csv_cmp;

use 5.010001;
use strict;
use warnings;
use Log::ger;

our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2026-07-09'; # DATE
our $DIST = 'App-CSVUtils'; # DIST
our $VERSION = '1.038'; # VERSION

use App::CSVUtils qw(
                        gen_csv_util
                );

gen_csv_util(
    name => 'csv_cmp',
    summary => 'Compare two CSV files value by value',
    description => <<'MARKDOWN',

This utility is modelled after the Unix command `cmp`; it compares two CSV files
value by value and ignore quoting (and can be instructed to ignore whitespaces,
case difference).

If all the values of two CSV files are identical, then utility will exit with
code 0. If a value differ, this utility will stop, print the difference and exit
with code 1.

If `-l` (`--detail`) option is specified, all differences will be reported. Note
that in `cmp` Unix command, the `-l` option is called `--verbose`. The detailed
report is in the form of CSV:

    rownum,fieldnum,value1,value2

where `rownum` begins at 1 (for header row), `fieldnum` begins at 1 (first
field), `value1` is the value in first CSV file, `value2` is the value in the
second CSV file.

Other notes:

* If none of the field selection options are used, it means all fields are
  included (equivalent to `--include-all-fields`).

* Field selection will be performed on the first CSV file, then the indexes will
be used for the second CSV file.

MARKDOWN
    add_args => {
        %App::CSVUtils::argspecsopt_field_selection,
        %App::CSVUtils::argspecsopt_show_selected_fields,

        detail => {
            summary => 'Report all differences instead of just the first one',
            schema => 'true*',
            cmdline_aliases => {l=>{}},
        },
        quiet => {
            summary => 'Do not report, just signal via exit code',
            schema => 'true*',
            cmdline_aliases => {q=>{}},
        },
        ignore_case => {
            summary => 'Ignore case difference',
            schema => 'bool*',
            cmdline_aliases => {i=>{}},
        },
        ignore_leading_ws => {
            summary => 'Ignore leading whitespaces',
            schema => 'bool*',
        },
        ignore_trailing_ws => {
            summary => 'Ignore trailing whitespaces',
            schema => 'bool*',
        },
        ignore_ws => {
            summary => 'Ignore leading & trailing whitespaces',
            schema => 'bool*',
        },
    },
    tags => [
        'accepts-regex', # for selecting fields
        'category:comparing',
    ],

    examples => [
        {
            summary => 'Compare two identical files, will output nothing and exits 0',
            argv => ['file.csv', 'file.csv'],
            test => 0,
            'x.doc.show_result' => 0,

lib/App/CSVUtils/csv_cmp.pm  view on Meta::CPAN

            $exit_code = 1;
            goto DONE unless $r->{util_args}{detail};
        } elsif ($numrows1 < $numrows2) {
            warn "csv-cmp: EOF: first CSV only has $numrows1 row(s) (vs $numrows2)\n"
                unless $r->{util_args}{quiet};
            $exit_code = 1;
            goto DONE unless $r->{util_args}{detail};
        }

      DONE:
        $r->{result} = [200, "OK", "", {"cmdline.exit_code"=>$exit_code}];
    },
);

1;
# ABSTRACT: Compare two CSV files value by value

__END__

=pod

=encoding UTF-8

=head1 NAME

App::CSVUtils::csv_cmp - Compare two CSV files value by value

=head1 VERSION

This document describes version 1.038 of App::CSVUtils::csv_cmp (from Perl distribution App-CSVUtils), released on 2026-07-09.

=head1 FUNCTIONS


=head2 csv_cmp

Usage:

 csv_cmp(%args) -> [$status_code, $reason, $payload, \%result_meta]

Compare two CSV files value by value.

Examples:

=over

=item * Compare two identical files, will output nothing and exits 0:

 csv_cmp(input_filenames => ["file.csv", "file.csv"]);

=item * Compare two CSV files case-insensitively (-i), show detailed report (-l):

 csv_cmp(
     input_filenames => ["file1.csv", "file2.csv"],
   detail => 1,
   ignore_case => 1
 );

=back

This utility is modelled after the Unix command C<cmp>; it compares two CSV files
value by value and ignore quoting (and can be instructed to ignore whitespaces,
case difference).

If all the values of two CSV files are identical, then utility will exit with
code 0. If a value differ, this utility will stop, print the difference and exit
with code 1.

If C<-l> (C<--detail>) option is specified, all differences will be reported. Note
that in C<cmp> Unix command, the C<-l> option is called C<--verbose>. The detailed
report is in the form of CSV:

 rownum,fieldnum,value1,value2

where C<rownum> begins at 1 (for header row), C<fieldnum> begins at 1 (first
field), C<value1> is the value in first CSV file, C<value2> is the value in the
second CSV file.

Other notes:

=over

=item * If none of the field selection options are used, it means all fields are
included (equivalent to C<--include-all-fields>).

=item * Field selection will be performed on the first CSV file, then the indexes will
be used for the second CSV file.

=back

This function is not exported.

Arguments ('*' denotes required arguments):

=over 4

=item * B<detail> => I<true>

Report all differences instead of just the first one.

=item * B<exclude_field_pat> => I<re>

Field regex pattern to exclude, takes precedence over --field-pat.

=item * B<exclude_fields> => I<array[str]>

Field names to exclude, takes precedence over --fields.

=item * B<ignore_case> => I<bool>

Ignore case difference.

=item * B<ignore_leading_ws> => I<bool>

Ignore leading whitespaces.

=item * B<ignore_trailing_ws> => I<bool>

Ignore trailing whitespaces.

=item * B<ignore_unknown_fields> => I<bool>

When unknown fields are specified in --include-field (--field) or --exclude-field options, ignore them instead of throwing an error.

=item * B<ignore_ws> => I<bool>

Ignore leading & trailing whitespaces.

=item * B<include_field_pat> => I<re>



( run in 2.834 seconds using v1.01-cache-2.11-cpan-64ef6c95b5d )