2010-04-02 31 views
4

我需要刪除給定文件夾下的所有內容(文件和文件夾)。問題是文件夾裏面有數百萬個文件和文件夾。所以我不想一次加載所有文件名使用Perl刪除非常龐大的文件夾的最佳策略是什麼?

邏輯應該是這樣的:

  • 遍歷文件夾空載一切
  • 得到一個文件或文件夾
  • 刪除 (詳細的文件或文件夾「X」已被刪除)
  • 去下一個

我很牛逼rying是這樣的:

sub main(){ 
    my ($rc, $help, $debug, $root) =(); 
    $rc = GetOptions ("HELP"   => \$help, 
        "DEBUG"   => \$debug, 
        "ROOT=s"   => \$root); 

    die "Bad command line options\n$usage\n" unless ($rc); 
    if ($help) { print $usage; exit (0); } 

    if ($debug) { 
     warn "\nProceeding to execution with following parameters: \n"; 
     warn "===============================================================\n"; 
     warn "ROOT = $root\n"; 

    } # write debug information to STDERR 

    print "\n Starting to delete...\n"; 

    die "usage: $0 dir ..\n" unless $root; 
    *name = *File::Find::name; 
    find \&verbose, @ARGV; 

} 

sub verbose { 
    if (!-l && -d _) { 
     print "rmdir $name\n"; 
    } else { 
     print "unlink $name\n"; 
    } 
} 

main(); 

它的正常工作,但每當「發現」讀取龐大文件夾,該應用被卡住,我可以看到系統內存爲Perl增加,直到超時。爲什麼?它試圖一次加載所有文件嗎?

感謝您的幫助。

+0

的** **的問題僅僅是,如果你讓一個問題一個問題。你爲什麼要寫'rm'或'rd/q/s'(取決於你的操作系統)? – 2010-04-02 17:03:27

+0

我不同意使用rm或rd更好。使用perl builtins更便於攜帶。 – frankc 2010-04-02 17:11:49

+0

我需要通過文件刪除文件和詳細的這是否有可能?我在Windows S.O.而rmdir剛剛卡住了。我想詳細說明這個過程。 – 2010-04-02 17:26:38

回答

6

perlfaq指出File::Find確實遍歷目錄的辛勤工作,但工作並不難(假設你的目錄樹是免費的命名管道,塊設備等):

sub traverse_directory { 
    my $dir = shift; 
    opendir my $dh, $dir; 
    while (my $file = readdir($dh)) { 
     next if $file eq "." || $file eq ".."; 
     if (-d "$dir/$file") { 
      &traverse_directory("$dir/$file"); 
     } elsif (-f "$dir/$file") { 
      # $dir/$file is a regular file 
      # Do something with it, for example: 
      print "Removing $dir/$file\n"; 
      unlink "$dir/$file" or warn "unlink $dir/$file failed: $!\n"; 
     } else { 
      warn "$dir/$file is not a directory or regular file. Ignoring ...\n"; 
     } 
    } 
    closedir $dh; 
    # $dir might be empty at this point. If you want to delete it: 
    if (rmdir $dir) { 
     print "Removed $dir/\n"; 
    } else { 
     warn "rmdir $dir failed: $!\n"; 
    } 
} 

用您自己的代碼替換文件或(可能)空白的目錄,然後在要處理的樹的根上調用此函數一次。查詢opendir/closedir,readdir,-d-f的含義,如果以前沒有遇到過。

+0

謝謝,我會盡力讓你知道。 – 2010-04-02 19:21:05

+0

U-huuu!它正在工作!非常感謝@mobrule! – 2010-04-02 19:34:09

+0

我在第3行'opendir my $ dh,$ dir;'中出錯了。用下面的代替來解決它:'my $ dh; \t opendir $ dh,$ dir;'其餘的代碼工作正常。謝謝 – Pit 2011-01-11 15:03:26

6

出了什麼問題:

`rm -rf $folder`; // ?? 
+0

我想詳細說明這個過程,我可以嗎? – 2010-04-02 17:27:15

+0

'rm'有一個'-v'選項,它可以在unix-like操作系統下做你想做的事情,但是正如你所說你在Windows下,這對你沒有任何幫助。 – 2010-04-02 17:37:05

+1

@Adam - 有DOS端口(許多)的Unix命令。我敢打賭,其中一個,可以做到這一點:) – DVK 2010-04-03 00:29:26

4

您可以使用File::Find系統地遍歷目錄,刪除文件和目錄下了。

+0

我很想問,*點會是什麼?* – 2010-04-02 17:03:55

+0

@Sinan:OP不想刪除父目錄。 – codaddict 2010-04-02 17:07:50

+0

我想詳細說明所有的過程。 – 2010-04-02 17:30:36

2

OK,我給中和使用Perl的內置函數,但你應該使用File::Path::rmtree,我已經完全忘記了:

#!/usr/bin/perl 

use strict; use warnings; 
use Cwd; 
use File::Find; 

my ($clean) = @ARGV; 
die "specify directory to clean\n" unless defined $clean; 

my $current_dir = getcwd; 
chdir $clean 
    or die "Cannot chdir to '$clean': $!\n"; 

finddepth(\&wanted => '.'); 

chdir $current_dir 
    or die "Cannot chdir back to '$current_dir':$!\n"; 

sub wanted { 
    return if /^[.][.]?\z/; 
    warn "$File::Find::name\n"; 
    if (-f) { 
     unlink or die "Cannot delete '$File::Find::name': $!\n"; 
    } 
    elsif (-d _) { 
     rmdir or die "Cannot remove directory '$File::Find::name': $!\n"; 
    } 
    return; 
} 
+0

感謝您的回覆,但每當「查找」函數讀取hude文件夾時,應用程序都會停滯不前,我可以看到Perl的系統內存增加,直到超時。爲什麼?它試圖一次加載所有文件嗎?任何想法? – 2010-04-02 18:42:08

7

File::Path可以便攜冗長remove_tree功能刪除一個目錄層次結構,如果需要,保持頂層目錄。

use strict; 
use warnings; 
use File::Path qw(remove_tree); 

my $dir = '/tmp/dir'; 
remove_tree($dir, {verbose => 1, keep_root => 1}); 

預5.10,從File::Path使用rmtree功能。如果你仍然想要頂層目錄,你可以再次使用mkdir

use File::Path; 

my $dir = '/tmp/dir'; 
rmtree($dir, 1); # 1 means verbose 
mkdir $dir; 
+0

感謝您的回覆,但每當「rmtree」函數讀取hude文件夾時,應用程序都會卡住,我可以看到我的Perl應用程序的系統內存正在增加。爲什麼?它試圖一次加載所有文件嗎?任何想法如何避免這種情況? – 2010-04-02 19:03:08

+1

是的,顯然它是。它加載目錄中的所有東西以遞歸刪除它們。看起來沒有理由不能進行迭代。見http://github.com/gitpan/File-Path/blob/master/Path.pm#L333 – Schwern 2010-04-03 20:57:31

1

下載unix tools for windows然後你可以做rm -rv或其他什麼。

Perl是一個用於很多目的的很好的工具,但是這一個似乎更好用專門的工具完成。

+0

十年未更新。改用它:http://gnuwin32.sf.net/ – daxim 2010-04-02 21:59:11

0

這是一種廉價的「跨平臺」的方法:

use Carp qw<carp croak>; 
use English qw<$OS_NAME>; 
use File::Spec; 

my %deltree_op = (nix => 'rm -rf %s', win => 'rmdir /S %s'); 

my %group_for 
    = ((map { $_ => 'nix' } qw<linux UNIX SunOS>) 
     , (map { $_ => 'win' } qw<MSWin32 WinNT> ) 
    ); 

my $group_name = $group_for{$OS_NAME}; 
sub chop_tree { 
    my $full_path = shift; 
    carp("No directory $full_path exists! We're done.") unless -e $full_path; 
    croak("No implementation for $OS_NAME!") unless $group_name; 
    my $format = $deltree_op{$group_name}; 
    croak("Could not find command format for group $group_name") unless $format; 
    my $command = sprintf($format, File::Spec->canonpath($full_path)); 
    qx{$command}; 
} 
相關問題