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 )