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

Hi,

I am using File::Copy to copy files from source to target directory. For running shell commands i can use system or back quote (`), but somebody told me that system will draw more memory , i.e execution time will be more when compared to inbuilt Perl packages. So i stared using File::Copy. But it is failed to copy file saying error "Inappropriate ioctl for device". i Have used copy like this

eval{ copy("$source" ,"$target_input_file"); }; if($!) { open(FAIL,">>failed_copy_$channel"); print FAIL"FAILED TO Copy \"$target\" WITH FROM \"$target_input_file\" +....\n"; close(FAIL); }


Please guide me whether the problem with "eval" or copy statement i have used...

Thanks,
Shekar KCB

Replies are listed 'Best First'.
Re: copy - Inappropriate ioctl for device
by Anonymous Monk on Feb 10, 2009 at 07:09 UTC
    Checking $! is misleading. File::Copy docs show example you need to follow
    copy("file1","file2") or die "Copy failed: $!";
    There is no need for eval because copy won't die on failure.
      Eh!? You can't say that eval is unnecessary on the grounds that it won't die, and in the same breath suggest a solution that does die and doesn't catch it with eval! (Unless maybe it's a Zen thing.)

      In order to avoid eval, and also do what the OP wanted in the error case, how about:

      use strict; use warnings; use File::Copy; my $source = "velocity.log"; my $target_input_file = "/tmp/not/there"; copy("$source" ,"$target_input_file") or do { open(FAIL,">>error.log"); print FAIL "FAILED TO Copy \"$source\" TO \"$target_input_file +\" +....\n"; close(FAIL); }
      Of course, this still doesn't directly answer the question as to why the error message "Inappropriate ioctl for device" pops up. For that part, I wouldn't expect that $! (aka errno) would be set as a side efect of the copy function or the eval. Maybe it's a side effect of something earlier in the program?

      The acid test: does the file get copied?

      --
      use JAPH;
      print JAPH::asString();

Re: copy - Inappropriate ioctl for device
by lakshmananindia (Chaplain) on Feb 10, 2009 at 07:13 UTC
    use strict; use warnings; use File::Copy; my $source="im"; my $target_input_file="/home/lakshmanan/Perl/"; my($channel,$target); eval{ copy("$source" ,"$target_input_file"); }; if($!) { open(FAIL,">>failed_copy_$channel"); print FAIL"FAILED TO Copy \"$target\" WITH FROM \"$target_input_fi +le\" +....\n"; close(FAIL); }

    The above code works fine for me

    Check your program with strict and warnings

      $! is only modified on failure. Most if not all functions leave it alone on success. This means if the copy succeeds, then $! is set to whatever it was before copy() was called -- which, given the nature of $!, is probably an error result, but might be success, as lakshmananindia noted.

      wol's solution is best, because it doesn't rely on $! to figure out whether the copy succeeded.

      Hi,

      Thank you all for the reply, i have re wrote my code, this whole code is embed in some big function, source file size is too large , may be this is the issue, (For info, this code works for small files, or make explicitly run) even after using die, or the code with strict and warnings, i am unable to get out of " Inappropriate ioctl for device ", hence closing the thread. Finally i am using this code for copying files

      $ret_value=system("copy \"$source\" \"$target\""); if($ret_value ne 0) { open(FAIL,">>failed_copy_$channel"); print FAIL"FAILED TO Copy \"$target\" WITH FROM \"$target_input_fi +le\" +....\n"; close(FAIL); }

      This works fine if used explicitly or used inside any program, or used to copy large files (more than 1MB also)

      Thank you all for your support,
      ShekarKCB
        ...strict and warnings, i am unable to get out of " Inappropriate ioctl for device "...
        Your mistake was checking $! when you weren't supposed to.

        Do not use $! to determine if a failure occured.

        perlvar says the value of $! is meaningful only immediately after a failure:

        if (open(FH, $filename)) { # Here $! is meaningless. ... } else { # ONLY here is $! meaningful. ... # Already here $! might be meaningless. } # Since here we might have either success or failure, # here $! is meaningless.
Re: copy - Inappropriate ioctl for device
by Anonymous Monk on Feb 10, 2009 at 07:12 UTC
    Always write code like
    open(...) or die "couldn't open ... $!";
    or if you're feeling bold
    use autodie qw( open close );
      You're half right. Always check for errors, and always handle them. But you shouldn't use xxx or die unless you can afford to die.
        Its always affordable when developing new program :)