in reply to Passing a very long parameter list to an external command in perl

OK, I've been asked to provide a bit more detail and provide a code sample. The external program is the command line interface to the Responsys Interact system

In my script, I have a call that goes like:
my $editcampaign = $cliObj->editcampaign( campaign => "Fake_Test_Campaign", folder => "Big_Fake_Directory_For_testing_only", dist => "Big_Fake_Directory_For_testing_only test_data_source", html => "Big_Fake_Directory_For_testing_only fake_file.htm", aol => "Big_Fake_Directory_For_testing_only fake_file.aol", text => "Big_Fake_Directory_For_testing_only fake_file.txt", autosense => 1, );

Then with in the package I'm building, I'm generating the command string with:

sub editcampaign { my $self = shift; my( $data, $ret ); ( @_ ) ? ( %$data ) = @_ : return; return if ( ( !$data->{'campaign'} ) or ( scalar( keys %$data ) < +1 ) ) ; push @$ret, qq|-locale $data->{'locale'}| if ( $data->{'locale' +} ); push @$ret, qq|-folder $data->{'folder'}| if ( $data->{'folder' +} ); push @$ret, qq|-ackurl $data->{'ackurl'}| if ( $data->{'ackurl' +} ); push @$ret, qq|-followup $data->{'followup'}| if ( $data->{'fol +lowup'} ); push @$ret, qq|-test $data->{'test'}| if ( $data->{'test'} +); push @$ret, qq|-optout $data->{'optout'}| if ( $data->{'optout' +} ); push @$ret, qq|-dist $data->{'dist'}| if ( ( $data->{'dist' +} ) and ( $data->{'dist'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-html $data->{'html'}| if ( ( $data->{'html' +} ) and ( $data->{'html'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-text $data->{'text'}| if ( ( $data->{'text' +} ) and ( $data->{'text'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-aol $data->{'aol'}| if ( ( $data->{'aol'} ) + and ( $data->{'aol'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-attach $data->{'attach'}| if ( ( $data->{'attac +h'} ) and ( $data->{'attach'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-sentlog $data->{'sentlog'}| if ( ( $data->{'sen +tlog'} ) and ( $data->{'sentlog'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-ackdoc $data->{'ackdoc'}| if ( ( $data->{'ackdo +c'} ) and ( $data->{'ackdoc'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-responsedb $data->{'responsedb'}| if ( ( $data- +>{'responsedb'} ) and ( $data->{'responsedb'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-failedlog $data->{'failedlog'}| if ( ( $data->{ +'failedlog'} ) and ( $data->{'failedlog'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-clicktrack $data->{'clicktrack'}| if ( ( $data- +>{'clicktrack'} ) and ( $data->{'clicktrack'} =~ /(.*) (.*)/ ) ); push @$ret, qq|-clickthru $data->{'clickthru'}| if ( ( $data->{ +'clickthru'} ) and ( $data->{'clickthru'} =~ /(.*) (.*) (.*) (.*)/ ) +); push @$ret, qq|-skipdup ON| if ( $data->{'locale'} ); push @$ret, qq|-autosense ON| if ( $data->{'autosense'} ); push @$ret, qq|-opensense ON| if ( $data->{'opensense'} ); push @$ret, qq|-useaccountwide ON| if ( $data->{'useaccountwide +'} ); push @$ret, qq|-conversiontrack ON| if ( $data->{'conversiontra +ck'} ); push @$ret, qq|-htmltoaol ON| if ( $data->{'htmltoaol'} ); push @$ret, qq|-autosenseaol ON| if ( ( $data->{'autosenseaol'} + ) and ( ( $data->{'autosense'} ) or ( $data->{'opensense'} ) ) ) ; push @$ret, $data->{'campaign'}; $ret = join " ", @$ret; # Log action $self->{'LOGGER'}->log( level => 'notice', message => "campaign $r +et\n" ); #execute it ( $ret ) = $self->executeCommand( "campaign $ret" ); return 1; }

The executeCommand call is the code provided in http://www.perlmonks.com/index.pl?node_id=151886 with a few minor tweeks made for logging and returning the results set.

Interesting side note: when I try this from the command line, I get a return saying:
Warning!!! Turning skip multipart OFF since auto-sense is used.
and the command still executes, setting all of the things I care about.

Any thoughts?

P.S. I will also gladly accept any style hints/pointers involved with creating the command line string.

Replies are listed 'Best First'.
Re: Re: Passing a very long parameter list to an external command in perl
by BrowserUk (Patriarch) on Oct 23, 2003 at 23:11 UTC

    There is no executeCommand() sub in Re: IPC::Open3 woes? (I checked 3 times:)


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Hooray!

Re: Re: Passing a very long parameter list to an external command in perl
by iburrell (Chaplain) on Oct 24, 2003 at 20:34 UTC
    How are you executing the command? This is pretty important. If you can use system with a list of arguments instead of a single string. From your code, you are likely using the single argument form of system which has all the quoting and length limits of the shell.
    $ret = join " ", @$ret; #execute it ( $ret ) = $self->executeCommand( "campaign $ret" )
    Since you already have the list of arguments, you can use that. You will have to use the array form of system. If you need to read the stdout of the program, I think that IPC::Open3 supports an array of arguments.
    system('campaign', @$ret);

      After finally getting it through my thick skull, I skipped the whole $ret = join " ", @$ret; and now simply pass the array to the sub.

      It works vewry well thank you!!

      Thanks for finally doing it jburrel!!!