YuTsun has asked for the wisdom of the Perl Monks concerning the following question:

Enlightened ones:

The zip command string below works as expected from the commandline on both Solaris and Mac OS X: the paths are excluded and I get a zip file containing only the files matching *.$fileext. But when I run the same command via Perl system() in a CGI script, the zip file contains empty directories for the full path from host root down to htdocs, with the files in the last directory.

Both the commandline and system() cases send the expected STDOUT to the file $joblog, and nothing shows up in the file $joberrors.

This command line excludes directories as advertised in man zip:

# /usr/bin/zip -D $zipfile $somepath/*.$fileext 1>$joblog 2>$joberrors

This system call does not:

$zipcommand = "/usr/bin/zip -D $zipfile $somepath/*.$fileext 1>$joblog + 2>$joberrors"; system("$zipcommand");

I noticed a similar question with tar on stackoverflow.com: How do i make a “system call to tar files(along with exclude tag)” to work in Perl.

Is there something about passing commandline switches that I am missing?

Replies are listed 'Best First'.
Re: Why doesn't system("zip -D") exclude directories?
by ikegami (Patriarch) on May 05, 2010 at 18:01 UTC

    A common error is to make bad assumptions about the current work directory.

    The only difference between system() and the command line is that the shell is interactive in the later. This can affect which startup files the shell executes, which could affect stuff like aliases.

    Finally, the command you're running via system might be different than the one you run from the command line. You should check the contents of the relevant variables.

    And that's assuming you're running the command as the same user.

      Thank you. As near as I can tell, though, the relevant environments are the same (I'm self-taught though, so that may not be saying much).

      With the variables expanded, the command line looks like this, whether called from system() or from the commandline:

      /usr/bin/zip -D /var/apache2/htdocs/appspace/output/test.zip /var/apac +he2/htdocs/appspace/output/*.[Mm][Ii][Ff] 1>>/var/apache2/htdocs/apps +pace/log/job.log 2>>/var/apache2/htdocs/appspace/log/error.log

      I run both the command line and the script in /var/apache2/cgi-bin, and both run as "root". Moreover, the behavior is identical on my Mac OS X laptop and on a remote Solaris 11 server. I am using the same "zip" in each case, as nearly as I can tell:

      # which zip /usr/bin/zip

      Is there some shell variable that might affect this other than which executable shell points to in each case?

        Using the same paths as you (except for adding a leading /tmp), I was unable to replicate your problem.
        Reading zip manual: there might be ZIPOPT variable holding options for zip.
Re: Why doesn't system("zip -D") exclude directories?
by marto (Cardinal) on May 05, 2010 at 17:42 UTC

    See system for examples of passing arguments.

      What would I be looking for? I of course checked perldoc before asking my question. As near as I can see, I have passed the arguments correctly.

      If you mean that I should pass the arguments in an array, I have tried passing arguments as an array but this made no difference: the directories were included in the zip file.

      @zipcommand = ("/usr/bin/zip", "-D", "$zipfile", "$somepath/*.$fileex +t");

      Moreover, when I use the array method, zip interprets the commandline redirects as filenames and cannot match the files if $fileext is a glob pattern like "*.jpg".