parallel: Better error message if Text::CSV is not installed.

This commit is contained in:
Ole Tange 2022-11-15 21:36:53 +01:00
parent 77e9f59abb
commit e40d44c517
6 changed files with 65 additions and 47 deletions

25
NEWS
View file

@ -8,21 +8,30 @@ New in this release:
News about GNU Parallel: News about GNU Parallel:
* Distributed Task Processing with GNU Parallel https://www.youtube.com/watch?v=usbMLggdMgc * Distributed Task Processing with GNU Parallel
https://www.youtube.com/watch?v=usbMLggdMgc
* GNU Parallel workflow for many small, independent runs https://docs.csc.fi/support/tutorials/many/ * GNU Parallel workflow for many small, independent runs
https://docs.csc.fi/support/tutorials/many/
* Copy a File To Multiple Directories With A Single Command on Linux https://www.linuxfordevices.com/tutorials/linux/copy-file-to-multiple-directories-with-one-command * Copy a File To Multiple Directories With A Single Command on Linux
https://www.linuxfordevices.com/tutorials/linux/copy-file-to-multiple-directories-with-one-command
* Behind The Scenes: The Power Of Simple Command Line Tools At Cloud Scale https://blog.gdeltproject.org/behind-the-scenes-the-power-of-simple-command-line-tools-at-cloud-scale/ * Behind The Scenes: The Power Of Simple Command Line Tools At Cloud
Scale
https://blog.gdeltproject.org/behind-the-scenes-the-power-of-simple-command-line-tools-at-cloud-scale/
* Run lz4 compression in parallel using GNU parallel https://www.openguru.com/2022/09/ * Run lz4 compression in parallel using GNU parallel
https://www.openguru.com/2022/09/
* Xargs / Parallel With Code Examples https://www.folkstalk.com/2022/09/xargs-parallel-with-code-examples.html * Xargs / Parallel With Code Examples
https://www.folkstalk.com/2022/09/xargs-parallel-with-code-examples.html
* Parallel processing on a single node with GNU Parallel https://www3.cs.stonybrook.edu/~cse416/Section01/Slides/SeaWulfIntro_CSE416_09222022.pdf * Parallel processing on a single node with GNU Parallel
https://www3.cs.stonybrook.edu/~cse416/Section01/Slides/SeaWulfIntro_CSE416_09222022.pdf
* Using GNU parallel painlessly -- from basics to bioinformatics job orchestration https://www.youtube.com/watch?v=qypUdm-IE9c * Using GNU parallel painlessly -- from basics to bioinformatics job
orchestration https://www.youtube.com/watch?v=qypUdm-IE9c
20220922 20220922

View file

@ -4,6 +4,9 @@
Quote of the month: Quote of the month:
[GNU Parallel] is the most amazing tool ever invented for bioinformatics!
-- Istvan Albert https://www.ialbert.me/
Got around to using GNU parallel for the first time from a suggestion by @jdwasmuth ... now I'm wishing I started using this years ago Got around to using GNU parallel for the first time from a suggestion by @jdwasmuth ... now I'm wishing I started using this years ago
-- Stefan Gavriliuc @GavriliucStefan@twitter -- Stefan Gavriliuc @GavriliucStefan@twitter

View file

@ -2278,7 +2278,11 @@ sub parse_options(@) {
if(defined $opt::tmuxpane) { $opt::tmux = $opt::tmuxpane; } if(defined $opt::tmuxpane) { $opt::tmux = $opt::tmuxpane; }
if(defined $opt::colsep) { $Global::trim = 'lr'; } if(defined $opt::colsep) { $Global::trim = 'lr'; }
if(defined $opt::csv) { if(defined $opt::csv) {
$Global::use{"Text::CSV"} ||= eval "use Text::CSV; 1;"; if(not $Global::use{"Text::CSV"} ||= eval "use Text::CSV; 1;") {
::error("The perl module Text::CSV is not installed.");
::error("Try installing libtext-csv-perl or perl-Text-CSV.");
wait_and_exit(255);
}
$opt::colsep = defined $opt::colsep ? $opt::colsep : ","; $opt::colsep = defined $opt::colsep ? $opt::colsep : ",";
my $csv_setting = { binary => 1, sep_char => $opt::colsep }; my $csv_setting = { binary => 1, sep_char => $opt::colsep };
my $sep = $csv_setting->{sep_char}; my $sep = $csv_setting->{sep_char};
@ -2698,7 +2702,7 @@ sub check_invalid_option_combinations() {
sub init_globals() { sub init_globals() {
# Defaults: # Defaults:
$Global::version = 20221022; $Global::version = 20221115;
$Global::progname = 'parallel'; $Global::progname = 'parallel';
$::name = "GNU Parallel"; $::name = "GNU Parallel";
$Global::infinity = 2**31; $Global::infinity = 2**31;
@ -3551,18 +3555,18 @@ sub shell_quote_scalar_default($) {
# $string = string to be quoted # $string = string to be quoted
# Returns: # Returns:
# $shell_quoted = string quoted as needed by the shell # $shell_quoted = string quoted as needed by the shell
my $s = $_[0]; local $_ = $_[0];
if($s =~ /[^-_.+a-z0-9\/]/i) { if(/[^-_.+a-z0-9\/]/i) {
$s =~ s/'/'"'"'/g; # "-quote single quotes s/'/'"'"'/g; # "-quote '-quotes
$s = "'$s'"; # '-quote entire string $_ = "'$_'"; # '-quote entire string
$s =~ s/^''//; # Remove unneeded '' at ends s/^''//; # Remove unneeded '' at ends
$s =~ s/''$//; # (faster than s/^''|''$//g) s/''$//; # (faster than s/^''|''$//g)
return $s; return $_;
} elsif ($s eq "") { } elsif ($_ eq "") {
return "''"; return "''";
} else { } else {
# No quoting needed # No quoting needed
return $s; return $_;
} }
} }
@ -13152,19 +13156,22 @@ sub real_max_length() {
sub find_max($) { sub find_max($) {
my $string = shift; my $string = shift;
# This is slow on Cygwin, so give Cygwin users a warning # This is slow on Cygwin, so give Cygwin users a warning
if($^O eq "cygwin") { if($^O eq "cygwin" or $^O eq "msys") {
::warning("Finding the maximal command line length. ". ::warning("Finding the maximal command line length. ".
"This may take up to 1 minute.") "This may take up to 1 minute.")
} }
# Use an upper bound of 100 MB if the shell allows for infinite # Use an upper bound of 100 MB if the shell allows for infinite
# long lengths # long lengths
my $upper = 100_000_000; my $upper = 100_000_000;
my $lower;
# 1000 is supported everywhere, so the search can start anywhere 1..999 # 1000 is supported everywhere, so the search can start anywhere 1..999
# 324 makes the search much faster on Cygwin, so let us use that # 324 makes the search much faster on Cygwin, so let us use that
my $len = 324; my $len = 324;
do { do {
if($len > $upper) { return $len }; if($len > $upper) { return $len };
$lower = $len;
$len *= 16; $len *= 16;
::debug("init", "Maxlen: $lower<$len<$upper(".($upper-$lower)."): ");
} while (is_acceptable_command_line_length($len,$string)); } while (is_acceptable_command_line_length($len,$string));
# Then search for the actual max length between # Then search for the actual max length between
# last successful length ($len/16) and upper bound # last successful length ($len/16) and upper bound
@ -13190,23 +13197,7 @@ sub binary_find_max($$$) {
# Guessing too high is cheap. Guessing too low is expensive. # Guessing too high is cheap. Guessing too low is expensive.
my $split = ($^O eq "cygwin" or $^O eq "msys") ? 0.93 : 0.5; my $split = ($^O eq "cygwin" or $^O eq "msys") ? 0.93 : 0.5;
my $middle = int (($upper-$lower)*$split + $lower); my $middle = int (($upper-$lower)*$split + $lower);
::debug("init", "Maxlen: $lower<$middle<$upper: "); ::debug("init", "Maxlen: $lower<$middle<$upper(".($upper-$lower)."): ");
if (is_acceptable_command_line_length($middle,$string)) {
return binary_find_max($middle,$upper,$string);
} else {
return binary_find_max($lower,$middle,$string);
}
}
sub _binary_find_max($$$) {
# Given a lower and upper bound find the max (length or args) of a
# command line
# Returns:
# number of chars on the longest command line allowed
my ($lower, $upper, $string) = (@_);
if($lower == $upper or $lower == $upper-1) { return $lower; }
my $middle = int (($upper-$lower)/2 + $lower);
::debug("init", "Maxlen: $lower<$middle<$upper: ");
if (is_acceptable_command_line_length($middle,$string)) { if (is_acceptable_command_line_length($middle,$string)) {
return binary_find_max($middle,$upper,$string); return binary_find_max($middle,$upper,$string);
} else { } else {
@ -13232,7 +13223,7 @@ sub _binary_find_max($$$) {
# Force using non-built-in command # Force using non-built-in command
$prg ||= ::which("echo"); $prg ||= ::which("echo");
::qqx("$prg ".${string}x(($len-1-length $prg)/length $string)); ::qqx("$prg ".${string}x(($len-1-length $prg)/length $string));
::debug("init", "$len=$? "); ::debug("init", "$len=$?\n");
return not $?; return not $?;
} }
} }

View file

@ -988,15 +988,15 @@ B<env_parallel>
Show the estimated number of seconds before finishing. Show the estimated number of seconds before finishing.
This forces GNU B<parallel> to read all jobs before starting to find This forces GNU B<parallel> to read all jobs before starting to find
the number of jobs. GNU B<parallel> normally only reads the next job the number of jobs (unless you use B<--total-jobs>). GNU B<parallel>
to run. normally only reads the next job to run.
The estimate is based on the runtime of finished jobs, so the first The estimate is based on the runtime of finished jobs, so the first
estimate will only be shown when the first job has finished. estimate will only be shown when the first job has finished.
Implies B<--progress>. Implies B<--progress>.
See also: B<--bar> B<--progress> See also: B<--bar> B<--progress> B<--total-jobs>
=item B<--fg> =item B<--fg>
@ -1028,6 +1028,9 @@ Beware: If the fifo is never opened for reading, the job will block forever:
seq 1000000 | parallel --fifo echo This will block seq 1000000 | parallel --fifo echo This will block
seq 1000000 | parallel --fifo 'echo This will not block < {}' seq 1000000 | parallel --fifo 'echo This will not block < {}'
By using B<--fifo> instead of B<--cat> you may save I/O as B<--cat>
will write to a temporary file, whereas B<--fifo> will not.
Implies B<--pipe> unless B<--pipe-part> is used. Implies B<--pipe> unless B<--pipe-part> is used.
See also: B<--cat> B<--pipe> B<--pipe-part> See also: B<--cat> B<--pipe> B<--pipe-part>
@ -1203,11 +1206,11 @@ Example:
=item Z<> --halt now,fail=1 =item Z<> --halt now,fail=1
exit when the first job fails. Kill running jobs. exit when a job has failed. Kill running jobs.
=item Z<> --halt soon,fail=3 =item Z<> --halt soon,fail=3
exit when 3 jobs fail, but wait for running jobs to complete. exit when 3 jobs have failed, but wait for running jobs to complete.
=item Z<> --halt soon,fail=3% =item Z<> --halt soon,fail=3%
@ -1215,11 +1218,11 @@ exit when 3% of the jobs have failed, but wait for running jobs to complete.
=item Z<> --halt now,success=1 =item Z<> --halt now,success=1
exit when a job succeeds. Kill running jobs. exit when a job has succeeded. Kill running jobs.
=item Z<> --halt soon,success=3 =item Z<> --halt soon,success=3
exit when 3 jobs succeeds, but wait for running jobs to complete. exit when 3 jobs have succeeded, but wait for running jobs to complete.
=item Z<> --halt now,success=3% =item Z<> --halt now,success=3%
@ -1227,11 +1230,11 @@ exit when 3% of the jobs have succeeded. Kill running jobs.
=item Z<> --halt now,done=1 =item Z<> --halt now,done=1
exit when one of the jobs finishes. Kill running jobs. exit when a job has finished. Kill running jobs.
=item Z<> --halt soon,done=3 =item Z<> --halt soon,done=3
exit when 3 jobs finishes, but wait for running jobs to complete. exit when 3 jobs have finished, but wait for running jobs to complete.
=item Z<> --halt now,done=3% =item Z<> --halt now,done=3%
@ -1340,6 +1343,8 @@ See also: B<{}>
=item B<--joblog> I<logfile> =item B<--joblog> I<logfile>
=item B<--jl> I<logfile>
Logfile for executed jobs. Logfile for executed jobs.
Save a list of the executed jobs to I<logfile> in the following TAB Save a list of the executed jobs to I<logfile> in the following TAB

View file

@ -4,6 +4,13 @@
# #
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
par_csv_not_installed() {
echo '### Give error if CSV.pm is not installed when using --csv'
sudo parallel mv {} {}.hidden ::: /usr/share/perl5/Text/CSV.pm
stdout parallel --csv echo ::: this should give an error
sudo parallel mv {}.hidden {} ::: /usr/share/perl5/Text/CSV.pm
}
par_sem_dir() { par_sem_dir() {
echo '### bug #58985: sem stall if .parallel/semaphores is chmod 0' echo '### bug #58985: sem stall if .parallel/semaphores is chmod 0'
chmod 0 ~/.parallel/semaphores chmod 0 ~/.parallel/semaphores

View file

@ -5,6 +5,9 @@ par_bug56403 3 job3cjob3d
par_bug56403 1 job1a par_bug56403 1 job1a
par_bug56403 1 job1b par_bug56403 1 job1b
par_bug56403 2 job2cjob2d par_bug56403 2 job2cjob2d
par_csv_not_installed ### Give error if CSV.pm is not installed when using --csv
par_csv_not_installed parallel: Error: The perl module Text::CSV is not installed.
par_csv_not_installed parallel: Error: Try installing libtext-csv-perl or perl-Text-CSV.
par_delay_Xauto TODO: --retries for those that fail and --sshdelay par_delay_Xauto TODO: --retries for those that fail and --sshdelay
par_delay_Xauto ### bug #58911: --delay Xauto par_delay_Xauto ### bug #58911: --delay Xauto
par_delay_Xauto 0 par_delay_Xauto 0