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

I'm trying to delete a file after reading it here is the code i have for it.
while ( $filename = readdir(DIR) ) { if ( $filename =~ /\.txt$/i ) { my ($variable)=Read_File( $scan_dir, $filename ); Scan_File($variable); Send_Email($variable); unlink( $filename ); } }
Is it correct because it it not deleting the file like i want to.

Replies are listed 'Best First'.
Re: Deleting a File
by Joost (Canon) on Jun 19, 2007 at 23:48 UTC
      This is the error i get. "Can't unlink MWALARM_ETH21611B_20070530-0615560 t get_alarmfiles.pl line 42, <FILEREAD> line 1." the script and the file are in two different place. do i need some additional code?
        A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Deleting a File
by graff (Chancellor) on Jun 20, 2007 at 02:06 UTC
    There are a few things that would get in the way:
    • if your DIR handle was opened like this:
      my $path = "some/path" opendir( DIR, $path );
      then your unlink has to be like this:
      unlink "$path/$filename";
    • if the directory indicated by $path has write permission turned off (for the user running the script at least), the script won't be able to delete (or add or rename) files in that directory.

    Note that the permissions on the data file itself do not matter for "unlink" -- only the permissions on the directory containing the data file are important.

      >Note that the permissions on the data file itself do not matter for "unlink" -- only the permissions on the directory containing the data file are important.

      No, that's UNIX. On Windoze, to quote the MSDN:"To delete or rename a file, you must have either delete permission on the file or delete child permission in the parent directory".
      An attempt to delete an open file will fail, and that is probably what is happening here.
        This is probably Yet Another Good Reason to get rid of package-level filehandles in favour of lexical ones (even though we were not shown the code for Read_File, the use of package-level directory handles is a hint). It really strucks me that lexical filehandles were supported since 5.6 and yet the vast majority of the examples use non-lexical ones.

        Flavio
        perl -ple'$_=reverse' <<<ti.xittelop@oivalf

        Don't fool yourself.
Re: Deleting a File
by GrandFather (Saint) on Jun 20, 2007 at 02:48 UTC

    Is the file closed before you try to unlink it? Could another process have it open?


    DWIM is Perl's answer to Gödel
Re: Deleting a File
by shigetsu (Hermit) on Jun 20, 2007 at 03:20 UTC
    Could another process have it open?
    If phimtau123 is on a *nixy system he could dig in `lsof`s output with (e)grep to see whether by any chance, as Grandfather tried to clarify above, the file is being held open by another process.
      If phimtau123 is on a *nixy system he could dig in `lsof`s output with (e)grep

      Well, if he were on a UNIX system he wouldn't need to do that at all, because POSIX-compliant systems allow you to unlink files while they are being held open by another process, the process can continue reading/writing to the unlinked file but the file ceases to exist once the filehandle is closed. Also, greping lsof output for a filename is insanely wasteful, because it makes lsof pipe all the filenames of open files on the entire system to grep, which then throws most of them away. Instead, just do

      lsof <filename>

      All dogma is stupid.
Re: Deleting a File
by Moron (Curate) on Jun 20, 2007 at 13:38 UTC
    To quote a Dutch saying, "meten is weten" (measuring is knowing). Or to put it another way, not only do you need to take the general step of measuring return values from builtin and other calls but you often need to take the further step of taking further measurements where that wouldn't be enough! On unix and linux, one has the luxury of the shrink-wrapped machine (or new linux installation) having pretty the same user environment it's destined for in production and reasonable assumptions can be made about permissions and suchlike. With Windows in a corporate environment, not that I work with it, I'd probably overtest such things, but anyway, here is the kind of "paranoid lots of measuring" coding sytle I'd adopt. It's incomplete because a lot of work just the first time round developing the "Paradoze" package I'd put together, but this should give some idea what I'd be up to:
    use Paradoze; my $dh = Opendir( 'drwx', $dir ); # use standard "paranoid" routines while ( my $file = Readdir( 'rwx', $dh ) ) { my $path = "$dir/$file"; # do this anyway rather than expecting sa +me directory!! FileTests( 'rwx', "$dir/$file" ); # process the file } #... Paradoze.pm package Paradoze; # paranoid utilities for windows corporate environme +nts sub Opendir { my ( $mask, $path ) = @_; FileTests( $mask, $path ); opendir my $dh, $path or die "$! for path $path\n"; $dh; } sub Readdir { my ( $mask, $dh ) = @_; # ... } sub FileTests { my ( $mask, $path ) = @_; for my $test ( split( '', $mask ) { eval "( -$test $path )" or FTFatal( $test, $path )"; #... }
    __________________________________________________________________________________

    ^M Free your mind!

Re: Deleting a File
by c4onastick (Friar) on Jun 20, 2007 at 01:54 UTC
    Are you running this on a Win32 machine? I ran into the same problem too earlier on a Win32 machine. Ended up rewriting that section of code, so I'm not really sure why it started working the second time. Why doesn't perl run under the same user that calls it on Win32?
      Why doesn't perl run under the same user that calls it on Win32?
      It does