7 multicmd - Run multiple commands in series
11 multicmd [I<OPTIONS>] [--] I<COMMAND-1> I<ARGS-1> ";" I<COMMAND-2> I<ARGS-2> ";" ...
13 Run I<COMMAND-1>, I<COMMAND-2>, ... I<COMMAND-n> after each other,
14 similarly like shells would do, except not involving any shell.
20 =item -d, --delimiter I<STRING>
22 Set command delimiter to I<STRING>.
23 Default is a literal C<;> semicolon.
24 Probably need to shell-escape.
25 If you want C<--> (double dash) for delimiter, to avoid confusion, put it as:
30 Exit if a command did not run successfully (ie. non-zero exit status or signaled)
31 and do not run further commands.
32 Similar to bash(1)'s errexit (set -e) mode.
33 multicmd(1)'s exit code will be the failed command exit code
34 (128+B<n> if terminated by a signal B<n>).
40 Note, that C<;> (or the non-default delimiter set by B<--delimiter>) is a shell meta-char
41 in your shell, so you need to escape/quote it, but it's a separate literal argument
42 when you call multicmd(1) in other layers (eg. execve(2)),
43 so don't just stick to the preceding word. Ie:
45 B<WRONG>: multicmd date\; ls
47 B<WRONG>: multicmd 'date; ls'
49 B<WRONG>: multicmd 'date ; ls'
51 B<CORRECT>: multicmd date \; ls
53 B<CORRECT>: multicmd date ';' ls
57 multicmd(1) exit with the exit code of the last command.
62 use Getopt
::Long qw
/:config no_ignore_case no_bundling no_getopt_compat no_auto_abbrev require_order pass_through/;
71 'd|delimiter=s' => \
$Delimiter,
72 'e|errexit!' => \
$Errexit,
73 'help' => sub { pod2usage
(-exitval
=>0, -verbose
=>99); },
74 ) or pod2usage
(-exitval
=>2, -verbose
=>99);
76 # Getopt's pass_through mode leaves "--" there
77 shift @ARGV if $ARGV[0] eq '--';
81 pod2usage
(-exitval
=>2, -verbose
=>99);
89 if($arg eq $Delimiter)
92 $cmd_args[$cmd_idx] = [];
96 push @
{$cmd_args[$cmd_idx]}, $arg;
100 # filter out empty commands
101 @cmd_args = grep {@
$_} @cmd_args;
103 $last_cmd_ref = pop @cmd_args;
105 for my $cmd_ref (@cmd_args)
108 my $error_code = ${^CHILD_ERROR_NATIVE
};
110 my $sys_errno = int $!;
113 if($error_code == -1)
115 warn "$0: $cmd_ref->[0]: $sys_errmsg\n";
116 $exit_status = 125 + $sys_errno; # "file not found" becomes 127.
120 if(WIFSIGNALED
($error_code)) { $exit_status = 128 + WTERMSIG
($error_code); }
121 else { $exit_status = WEXITSTATUS
($error_code); }
124 if($Errexit and $exit_status != 0)
130 exec {$last_cmd_ref->[0]} @
$last_cmd_ref;
131 # if last command not found:
132 ($errno, $errstr) = (int $!, $!);
133 warn "$0: $last_cmd_ref->[0]: $errstr\n";