in reply to Whoops! I deleted everything!

Drop everything. Shut the server down if you can. Then read on. You can rescue large chunks of data

Shouldn't unlink only delete the files that go into @deletions?

It does. The problem is that $days is not passed into your deletion sub. This is because it is localised to package main:: (your code) but the sub is called in package File::Find where there is no var $days. As a result $days is == 0. As a result all files are too old as none of them have -M < 0. As a result all files get deleted. Getting out the all seeing RETROSPECTOSCOPE: If you had used warnings Perl would have cried about the uninitialised $days var for every call to &wanted (as well as the two my's BTW). If you had have used print as a test first you would have saved much pain - I always do these days having been made painfully aware of the awesome power of unlink with code that does not work as expected. If you unmount your file system right now and remount it read only you will be able to rescue some data. There is a node about doing that here somewhere. You have my sympathy. Been there. Deleted that. It hurts.

I am especially sorry for you as you have been doing the right thing and using strict. Remove strict and the my before $days and $days is global and......it works as expected. Ouch. This does not mean strict is bad but I would advise using it together with warnings as standard practice to catch these sort of issues.

Update

I can't find the link here I was after but http://recover.sourceforge.net/links/ is a good place to start. From your code you are on *nix so you want to unmount the partitions/disk(s) affected as read only and (perhaps) even boot from another disk. You can then recover data that has not already been overwritten. Don't expect miracles as you will get back raw inodes but if the data is vital, there are no good backups or your job is on the line...it may be worth it.
#!/usr/local/bin/perl use strict; use File::Find; #use warnings; # <--- this would have saved the day my $one_month = 'd:/sharedata/perl'; my $one_week = '/ftp/ftp/incoming'; # Traverse desired filesystems my $days = 30; File::Find::find({wanted => \&wanted}, $one_month); my $days = 7; File::Find::find({wanted => \&wanted}, $one_week); sub wanted { /software|patch|files/i and $File::Find::prune = 1; do { print "'$days' Skipping $File::Find::name\n" ; return } if (( +-d $_) || (int(-M $_) < $days)); push @deletions, "$File::Find::name"; print "'$days' Deleting: $File::Find::name\n" || die "Can't delete + file: $!"; } # notice the lack of a value for $days..... __DATA__ '' Skipping d:/sharedata/perl '' Skipping d:/sharedata/perl/Webmail3 '' Deleting: d:/sharedata/perl/Webmail3/AddresessBookExport Fields.txt '' Deleting: d:/sharedata/perl/Webmail3/config.pl '' Deleting: d:/sharedata/perl/Webmail3/convert.pl # with warnings ............... __DATA__ "my" variable $days masks earlier declaration in same scope at test.pl + line 17. Use of uninitialized value in numeric lt (<) at test.pl line 28. "my" variable $days masks earlier declaration in same scope at test.pl + line 17. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28. "my" variable $days masks earlier declaration in same scope at test.pl + line 17. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28. "my" variable $days masks earlier declaration in same scope at test.pl + line 17. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28. Use of uninitialized value in numeric lt (<) at test.pl line 28.

Bummer

tachyon

s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Replies are listed 'Best First'.
Re: Re: Whoops! I deleted everything!
by sauoq (Abbot) on Dec 11, 2002 at 00:50 UTC
    It does. The problem is that $days is not passed into your deletion sub. This is because it is localised to package main:: (your code) but the sub is called in package File::Find where there is no var $days. As a result $days is == 0.

    You were close. The fact that $days is a lexical doesn't actually make a difference. Notice that @deletions is also lexical and it doesn't cause any problems. The package that the sub is called from doesn't actually matter. The $days variable is indeed visible to the file in which the wanted sub is defined.

    The real gotcha here is that $days was declared twice. Basically, the second declaration causes the first to be completely ignored. It's like that whole line is commented out. So, on the first call, which takes place to the actual initialization, $days is still undefined. On the second call, it is properly initialized.

    -sauoq
    "My two cents aren't worth a dime.";
    

      Hmm, it is as you say....

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Re: Whoops! I deleted everything!
by Anonymous Monk on Dec 10, 2002 at 23:46 UTC

    What a Gotcha!

    Thanks for figuring it out. I was stumped. Thankfully the files are not that important (I think!). I might hear about it tomorrow, but I shouldn't be in too much trouble.

    It's time for me to buy a tape drive for that server!

    I will never forget this lesson.

      By the time you buy that tape drive , I might even have gotten around to re-writing the POD for Device::MagneticTape, which has undergone some pretty substantial changes of late, so if you are Talking to Magnetic Tapes try it.

      </shamelessplug>