# each filename is wrapped in quotes # so we only need to escape characters which have # special meaning to the shell - when it interpolates # in double-quotes. there are only 4 such characters, # namely " ` $ and \ # interestingly, newline is NOT one of these... sub quote_for_shell { my ($x) = @_; $x =~ s/([\"\`\$\\])/\\$1/g; return "\"" . $x . "\""; } @command_line = ( quote_for_shell( $prog1 ), quote_for_shell( $file1 ), "|", quote_for_shell( $prog2 ), "-x -y", "|", quote_for_shell( $prog3 ), ">", quote_for_shell( $file3 ) ) system join " ", @command_line;