2008-10-22 38 views

Trả lời

11

Tôi muốn làm điều gì đó như thế này:

use File::Copy; 
sub copy_recursively { 
    my ($from_dir, $to_dir, $regex) = @_; 
    opendir my($dh), $from_dir or die "Could not open dir '$from_dir': $!"; 
    for my $entry (readdir $dh) { 
     next if $entry =~ /$regex/; 
     my $source = "$from_dir/$entry"; 
     my $destination = "$to_dir/$entry"; 
     if (-d $source) { 
      mkdir $destination or die "mkdir '$destination' failed: $!" if not -e $destination; 
      copy_recursively($source, $destination, $regex); 
     } else { 
      copy($source, $destination) or die "copy failed: $!"; 
     } 
    } 
    closedir $dh; 
    return; 
} 
+0

Tôi nghĩ rằng bạn có một vấn đề (vòng lặp vô hạn) trong trường hợp $ regexp của bạn không khớp "." hoặc "..", là hai giá trị đầu tiên của $ entry được trả về bởi readdir. Nếu $ to_dir của bạn không tồn tại và $ source thực sự là thư mục, mkdir sẽ không thành công, tôi khuyên bạn nên sử dụng mkpath thay thế. – huitseeker

+0

. và .. không phải là một vấn đề trên Windows AFAIK, do đó, đó không phải là một vấn đề, nhưng đối với tính di động bạn đúng nó sẽ là tốt hơn để lọc những người ra. Đối với mkpath: cá nhân tôi nghĩ rằng một tình huống như vậy nên đưa ra một lỗi, nhưng đó là một vấn đề của hương vị. –

1

Tôi không biết làm thế nào để làm một loại trừ với một bản sao, nhưng bạn có thể làm việc gì đó dọc theo dòng:

ls -R1 | grep -v <regex to exclude> | awk '{printf("cp %s /destination/path",$1)}' | /bin/sh 
5

Nếu bạn tình cờ được trên một hệ điều hành Unix-like và có quyền truy cập đến rsync (1), bạn nên sử dụng điều đó (ví dụ: thông qua system()).

Tệp của Perl :: Bản sao bị hỏng một chút (không sao chép quyền trên hệ thống Unix), vì vậy nếu bạn không muốn sử dụng các công cụ hệ thống của mình, hãy xem CPAN. Có thể File::Copy::Recursive có thể được sử dụng, nhưng tôi không thấy bất kỳ tùy chọn loại trừ nào. Tôi hy vọng người khác có ý tưởng tốt hơn.

9

Một tùy chọn khác là Tệp :: Xcopy. Như tên cho biết, nó ít nhiều giả lập lệnh xcopy windows, bao gồm các tùy chọn lọc và đệ quy của nó.

Từ các tài liệu:

use File::Xcopy; 

    my $fx = new File::Xcopy; 
    $fx->from_dir("/from/dir"); 
    $fx->to_dir("/to/dir"); 
    $fx->fn_pat('(\.pl|\.txt)$'); # files with pl & txt extensions 
    $fx->param('s',1);    # search recursively to sub dirs 
    $fx->param('verbose',1);  # search recursively to sub dirs 
    $fx->param('log_file','/my/log/file.log'); 
    my ($sr, $rr) = $fx->get_stat; 
    $fx->xcopy;     # or 
    $fx->execute('copy'); 

    # the same with short name 
    $fx->xcp("from_dir", "to_dir", "file_name_pattern"); 
1

Một câu trả lời cổ điển sẽ sử dụng 'cpio -p ':

(cd $SOURCE_DIR; find . -type f -print) | 
perl -ne 'print unless m/<regex-goes-here>/' | 
cpio -pd $TARGET_DIR 

Các' cpio' giao dịch lệnh với việc sao chép thực tế, trong đó có bảo tồn được phép. Bí quyết của 'cd $SOURCE_DIR; find . ...' thỏa thuận với việc loại bỏ phần dẫn đầu của đường dẫn nguồn khỏi tên. Vấn đề duy nhất với lời gọi đó là 'find' là nó sẽ không theo các liên kết tượng trưng; bạn cần phải thêm '-follow' nếu đó là những gì bạn muốn.

+0

nào mà làm việc trên cửa sổ quá? – Manu

Các vấn đề liên quan