http://qs321.pair.com?node_id=343898

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

I am writing a little script to move all files from one directory to another, and delete the files from the original directory. This is what I have so far,
my $Error_Path = "\\\\server\\share\\new_error\\"; my $EAI_Error_Path = "\\\\server\\share\\old_error\\"; my $file; opendir DIR, $EAI_Error_Path; my @file = grep {$_ ne '.' && $_ ne '..'} readdir DIR; closedir DIR; foreach $file (@file){ $cmd = "copy \"".$EAI_Error_Path.$file[$i]."\" \"". $Error_Path.$f +ile[$i]."\""; system ($cmd) or die "?"; unlink $EAI_Error_Path.$file; $i++; } close MYFILE;
My question is, how do I check if the system command was succesful? Or, I only want to delete the file if it's been copied... Thanks monks.

Replies are listed 'Best First'.
Re: Check if "System" was succesful
by matija (Priest) on Apr 09, 2004 at 13:46 UTC

    You should check the value of $?.

    From perldoc perlvar:

        $?      The status returned by the last pipe close, backtick (``) command, successful call to wait() or waitpid(), or from the system() operator. This is just the 16-bit status word returned by the wait() system call (or else is made up to look like it).

    Thus, the exit value of the subprocess is really ("$? >> 8"), and "$? & 127" gives which signal, if any, the process died from, and "$? & 128" reports whether there was a core dump.

    (Mnemonic: similar to sh and ksh.)

    ...

    If you have installed a signal handler for "SIGCHLD", the value of $? will usually be wrong outside that handler.

    ....

    Also see "Error Indicators".

Re: Check if "System" was succesful
by arden (Curate) on Apr 09, 2004 at 13:42 UTC
    to get the return value of a  system command, just do:  my $returnValue = system(...); and determine if the code is what you want/expect.

    Of course, in your specific example, why don't you just do a DOS  MOVE instead of a  COPY &  unlink ? Again, you can capture the return codes from each move to put into a hash to know the number of files successfully and unsuccessfully moved (I'm assuming that's what you're using the  $i++ for.

    - - arden.

Re: Check if "System" was succesful
by vaevictus (Pilgrim) on Apr 09, 2004 at 13:39 UTC
    my first thought is to
    use File::Copy; my $status = copy("file1.txt","file2.txt"); if ($status) { print "good, now deleting\n"; unlink "file1.txt"; } else { print "bad, don't delete\n"; }
Re: Check if "System" was succesful
by JSchmitz (Canon) on Apr 09, 2004 at 13:50 UTC
    use the CPAN
    use File::NCopy qw(copy); copy "file","other_file"; copy "file1","file2","file3","directory"; # we want to copy the directory recursively copy \1,"directory1","directory2"; copy \1,"file1","file2","directory1","file3","directory2","file4", "directory"; # can also use references to file handles, this is for backward # compatibility with File::Copy copy \*FILE1,\*FILE2; copy \*FILE1,"file"; copy "file1",\*FILE2; # we don't specify \1 as the first argument because we don't want +to # copy directories recursively copy "*.c","*.pl","programs"; copy "*", "backup"; use File::NCopy; # the below are the default config values $file = File::NCopy->new( 'recursive' => 0, 'preserve' => 0, 'follow_links' => 0, 'force_write' => 0, 'set_permission' => \&File::NCopy::u_chmod, 'file_check' => \&File::NCopy::f_check, 'set_times' => \&File::NCopy::s_times, ); set_permission will take two file names, the original to get the file permissions from and the new file to set the file permissions for. file_check takes two parameters, the file names to check the file +to copy from and the file to copy to. I am using flock for Unix systems. Default for this is \&File::NCopy::f_check. On Unix you can also +use \&File::NCopy::unix_check. This one compares the inode and device numbers. set_times is used if the preserve attribute is true. It preserves the access and modification time of the file and also attempts to set the owner of the file to the original owner. This can be usef +ul in a script used by root, though enyone can preserve the access an +d modification times. This also takes two arguments. The file to ge +t the stats from and apply the stats to. On Unix boxes you shouldn't need to worry. On other system you ma +y want to supply your own sub references. $file = File::NCopy->new(recursive => 1); $file->copy "file","other_file"; $file->copy "directory1","directory2"; $file = File::NCopy->new(u_chmod => \&my_chmod,f_check => \&my_fch +eck); $file->copy "directory1","directory2";
Re: Check if "System" was succesful
by esskar (Deacon) on Apr 09, 2004 at 13:41 UTC
    hi.
    you better use use File::Copy to copy your files; and unlink returns the number of files it has deleteted.
Re: Check if "System" was succesful
by vaevictus (Pilgrim) on Apr 09, 2004 at 13:42 UTC
    but for a system related WTDI,
    my $result = system("copy bleh blah"); #system returns opposite ... IIRC if(! $result) { print "success\n"; } else { print "oh no!\n"; }

      The usual (and slightly more compact) way to check a system call is:

      system( $cmd ) == 0 or die "System call failed: $!";

      The " == 0" deals with the fact that system returns 0/false on success, not true like most perl functions.


      If the information in this post is inaccurate, or just plain wrong, don't just downvote - please post explaining what's wrong.
      That way everyone learns.

Re: Check if "System" was succesful
by nimdokk (Vicar) on Apr 09, 2004 at 14:02 UTC
    You could also try something like:

    use File::Spec; use File::Copy; my $file=File::Spec->catfile('\\serverA','dir','subdir','file'); my $newfile=File::Spec->catfile('\\serverB','dir','subdir','file'); my $errorfile=File::Spec->catfile('\\serverA','error_dir','file'); copy $file, $newfile or warn "Unable to copy $file to $newfile. $!"; if ($? > 0) { copy $file, $errorfile; } elsif ($? == 0) { unlink $file; }

    Or something along those lines, but what if you are unable to make the second copy? or what if you are unable to unlink or otherwise remove the file? I'd also recommend using File::Spec to help with the paths and directory seperators, helps make it a bit cleaner, IMO :-)

    update: Fixed the tags that were borked


    "Ex Libris un Peut de Tout"