App-CSVUtils
view release on metacpan or search on metacpan
lib/App/CSVUtils.pm view on Meta::CPAN
_
tags => ['category:output'],
},
);
our %argspecopt_input_filename = (
input_filename => {
summary => 'Input CSV file',
description => <<'_',
Use `-` to read from stdin.
Encoding of input file is assumed to be UTF-8.
_
schema => 'filename*',
default => '-',
'x.completion' => $xcomp_csvfiles,
tags => ['category:input'],
},
);
our %argspecopt_input_filenames = (
input_filenames => {
'x.name.is_plural' => 1,
'x.name.singular' => 'input_filename',
summary => 'Input CSV files',
description => <<'_',
Use `-` to read from stdin.
Encoding of input file is assumed to be UTF-8.
_
schema => ['array*', of=>'filename*'],
default => ['-'],
'x.completion' => $xcomp_csvfiles,
tags => ['category:input'],
},
);
our %argspecopt_overwrite = (
overwrite => {
summary => 'Whether to override existing output file',
schema => 'bool*',
cmdline_aliases=>{O=>{}},
tags => ['category:output'],
},
);
our %argspecsopt_inplace = (
inplace => {
summary => 'Output to the same file as input',
schema => 'true*',
description => <<'_',
Normally, you output to a different file than input. If you try to output to the
same file (`-o INPUT.csv -O`) you will clobber the input file; thus the utility
prevents you from doing it. However, with this `--inplace` option, you can
output to the same file. Like perl's `-i` option, this will first output to a
temporary file in the same directory as the input file then rename to the final
file at the end. You cannot specify output file (`-o`) when using this option,
but you can specify backup extension with `-b` option.
Some caveats:
- if input file is a symbolic link, it will be replaced with a regular file;
- renaming (implemented using `rename()`) can fail if input filename is too long;
- value specified in `-b` is currently not checked for acceptable characters;
- things can also fail if permissions are restrictive;
_
tags => ['category:output'],
},
inplace_backup_ext => {
summary => 'Extension to add for backup of input file',
schema => 'str*',
default => '',
description => <<'_',
In inplace mode (`--inplace`), if this option is set to a non-empty string, will
rename the input file using this extension as a backup. The old existing backup
will be overwritten, if any.
_
cmdline_aliases => {b=>{}},
tags => ['category:output'],
},
);
our %argspecopt_output_filename = (
output_filename => {
summary => 'Output filename',
description => <<'_',
Use `-` to output to stdout (the default if you don't specify this option).
Encoding of output file is assumed to be UTF-8.
_
schema => 'filename*',
cmdline_aliases=>{o=>{}},
tags => ['category:output'],
},
);
our %argspecopt_output_filenames = (
output_filenames => {
summary => 'Output filenames',
description => <<'_',
Use `-` to output to stdout (the default if you don't specify this option).
Encoding of output file is assumed to be UTF-8.
_
schema => ['array*', of=>'filename*'],
cmdline_aliases=>{o=>{}},
tags => ['category:output'],
},
);
our %argspecopt_field = (
field => {
summary => 'Field name',
schema => 'str*',
cmdline_aliases => { f=>{} },
completion => \&_complete_field,
},
);
our %argspecopt_field_1 = (
field => {
summary => 'Field name',
schema => 'str*',
pos => 1,
cmdline_aliases => { f=>{} },
completion => \&_complete_field,
},
);
our %argspec_field_1 = (
lib/App/CSVUtils.pm view on Meta::CPAN
# XXX actually close filehandle except stdin
if ($after_close_input_file) {
log_trace "[csvutil] Calling after_close_input_file handler ...";
$after_close_input_file->($r);
if (delete $r->{wants_skip_files}) {
log_trace "[csvutil] Handler wants to skip reading all file, skipping";
last READ_CSV;
}
}
} # for input_filename
if ($after_close_input_files) {
log_trace "[csvutil] Calling after_close_input_files handler ...";
$after_close_input_files->($r);
}
} # READ_CSV
# cleanup stash from csv-reading-related keys
delete $r->{input_filenames};
delete $r->{input_filenum};
delete $r->{input_filename};
delete $r->{input_fh};
delete $r->{input_rownum};
delete $r->{input_data_rownum};
delete $r->{input_row};
delete $r->{input_row_as_hashref};
delete $r->{input_fields};
delete $r->{input_fields_idx};
delete $r->{orig_input_fields_idx};
delete $r->{code_getline};
delete $r->{wants_input_row_as_hashref};
if ($after_read_input) {
log_trace "[csvutil] Calling after_read_input handler ...";
$after_read_input->($r);
}
# cleanup stash from csv-outputting-related keys
delete $r->{output_num_of_files};
delete $r->{output_filenum};
if ($r->{output_fh}) {
if ($r->{output_filename} ne '-') {
log_info "[csvutil] Closing output file '$r->{output_filename}' ...";
close $r->{output_fh} or die [500, "Can't close output file '$r->{output_filename}': $!"];
}
delete $r->{output_fh};
}
if ($r->{util_args}{inplace}) {
my $output_filenum = $r->{output_filenum} // 0;
my $i = -1;
for my $output_filename (@{ $r->{output_filenames} }) {
$i++;
last if $i > $output_filenum;
(my $input_filename = $output_filename) =~ s/\.\w{5}\z//
or die [500, "BUG: Can't get original input file '$output_filename'"];
if (length(my $ext = $r->{util_args}{inplace_backup_ext})) {
my $backup_filename = $input_filename . $ext;
log_info "[csvutil] Backing up input file '$output_filename' -> '$backup_filename' ...";
rename $input_filename, $backup_filename or die [500, "Can't rename '$input_filename' -> '$backup_filename': $!"];
}
log_info "[csvutil] Renaming from temporary output file '$output_filename' -> '$input_filename' ...";
rename $output_filename, $input_filename or die [500, "Can't rename back '$output_filename' -> '$input_filename': $!"];
}
}
delete $r->{output_filenames};
delete $r->{output_filename};
delete $r->{output_rownum};
delete $r->{output_data_rownum};
delete $r->{code_print};
delete $r->{code_print_row};
delete $r->{code_print_header_row};
delete $r->{has_printed_header};
delete $r->{wants_switch_to_next_output_file};
if ($on_end) {
log_trace "[csvutil] Calling on_end hook handler ...";
$on_end->($r);
}
}; # MAIN_EVAL
my $err = $@;
if ($err) {
$err = [500, $err] unless ref $err;
return $err;
}
RETURN_RESULT:
if (!$r->{result}) {
$r->{result} = [200];
} elsif (!ref($r->{result})) {
$r->{result} = [500, "BUG: Result (r->{result}) is set to a non-reference ($r->{result}), probably by one of the handlers"];
} elsif (ref($r->{result}) ne 'ARRAY') {
$r->{result} = [500, "BUG: Result (r->{result}) is not set to an enveloped result (arrayref) ($r->{result}), probably by one of the handlers"];
}
$r->{result};
};
} # CREATE_CODE
my $meta;
CREATE_META: {
$meta = {
v => 1.1,
summary => $summary,
description => $description,
args => {},
args_rels => {},
links => $links,
examples => $examples,
tags => $tags,
};
CREATE_ARGS_PROP: {
if ($add_args) {
$meta->{args}{$_} = $add_args->{$_} for keys %$add_args;
}
if ($reads_csv) {
$meta->{args}{$_} = {%{$argspecs_csv_input{$_}}} for keys %argspecs_csv_input;
if ($reads_multiple_csv) {
( run in 2.232 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )