2011-12-09 22 views
7

Chciałbym wziąć katalog i wszystkie pliki e-mail (* .msg), usunąć "RE" na początku. Mam następujący kod, ale zmiana nazwy kończy się niepowodzeniem.Używanie Perla do zmiany nazw plików w katalogu

opendir(DIR, 'emails') or die "Cannot open directory"; 
@files = readdir(DIR); 
closedir(DIR); 

for (@files){ 
    next if $_ !~ m/^RE .+msg$/; 
    $old = $_; 
    s/RE //; 
    rename($old, $_) or print "Error renaming: $old\n"; 
} 
+4

W przypadku drukowania błąd ($!) Można zorientować się, co się stało ... – pilcrow

+0

Dziękuję za wskazanie, że obecnie. Błąd to "Brak takiego pliku lub katalogu". Jestem zaskoczony, ponieważ stara nazwa pliku jest dokładna. – Johnathan1

+2

Należy zauważyć, że 'rename' nie korzysta z obsługi wielu platform, natomiast' File :: Copy''s 'move' ma funkcję – Zaid

Odpowiedz

9

Jeśli katalog ./emails zawiera następujące pliki:

1.msg 
2.msg 
3.msg 

wówczas @files będzie wyglądać mniej więcej tak ('.', '..', '1.msg', '2.msg', '3.msg') ale twój rename chce nazwiska jak 'emails/1.msg', 'emails/2.msg' itp więc można chdir przed zmianą nazwy:

chdir('emails'); 
for (@files) { 
    #... 
} 

Prawdopodobnie chcesz eck również zwraca wartość zwracaną przez chdir.

lub dodać nazwy katalogów siebie:

rename('emails/' . $old, 'emails/' . $_) or print "Error renaming $old: $!\n"; 
# or rename("emails/$old", "emails/$_") if you like string interpolation 
# or you could use map if you like map 

Możesz chcieć połączyć lektury katalogu i filtrowanie za pomocą grep:

my @files = grep { /^RE .+msg$/ } readdir(DIR); 

lub nawet to:

opendir(DIR, 'emails') or die "Cannot open directory"; 
for (grep { /^RE .+msg$/ } readdir(DIR)) { 
    (my $new = $_) =~ s/^RE //; 
    rename("emails/$_", "emails/$new") or print "Error renaming $_ to $new: $!\n"; 
} 
closedir(DIR); 
+0

Doskonały. Dziękuję za wyjaśnienie tego. – Johnathan1

5

ty wydaje się przyjmować raczej zachowanie podobne do glob niż readdir-podobne zachowanie.

Podstawowe wywołanie systemowe readdir zwraca tylko nazwy plików w katalogu i będzie zawierać dwa wpisy: . i ... To prowadzi do funkcji readdir w Perlu, tylko po to, aby dać więcej szczegółów na temat odpowiedzi mu.

Alternatywnie, nie ma sensu używać readdir, jeśli i tak zbieracie wszystkie wyniki w tablicy.

@files = glob('emails/*'); 
+0

+1 za przypomnienie mi, że "glob" istnieje. Wadą "globu" jest to, że nieco komplikuje to nazwę, ponieważ obecność prefiksu "e-maile /" jest dość niewielkim problemem i nie jest łatwe do rozwiązania. –

2

Jak już wspomniano, twój skrypt kończy się niepowodzeniem ze względu na oczekiwaną ścieżkę i skrypt nie jest taki sam.

Proponuję bardziej przejrzyste użycie. Hardcoding katalogu nie jest dobrym pomysłem, IMO. Jak się nauczyłem pewnego dnia, kiedy zrobiłem scenariusz, aby zmienić oryginalne pliki, z zakodowaną ścieżką, a mój kolega myślał, że to będzie dobry skrypt do pożyczenia, żeby zmienić jego kopie. Ooops!

Zastosowanie:

perl script.pl "^RE " *.msg 

to wyrażenie regularne, to lista plików glob, gdzie ścieżka jest oznaczona w stosunku do scenariusza, np *.msg, emails/*.msg lub nawet /home/pat/emails/*.msg /home/foo/*.msg. (wiele globusów możliwych)

Korzystanie z bezwzględnych ścieżek pozostawi użytkownika bez żadnych wątpliwości, do których plików on wpłynie, a także sprawi, że skrypt będzie ponownie używany.

Kod:

use strict; 
use warnings; 
use v5.10; 
use File::Copy qw(move); 

my $rx = shift; # e.g. "^RE " 

if ($ENV{OS} =~ /^Windows/) { # Patch for Windows' lack of shell globbing 
    @ARGV = map glob, @ARGV; 
} 

for (@ARGV) { 
    if (/$rx/) { 
     my $new = s/$rx//r; # Using non-destructive substitution 
     say "Moving $_ to $new ..."; 
     move($_, $new) or die $!; 
    } 
} 
+0

+1: Uwielbiam uniksowy system Windows :) – Zaid

+0

Witam, bardzo podoba mi się ten pomysł. Wygląda na to, że dostaję błąd w wierszu my $ new = s/$ rx // r. Wyjście to "boskie słowo znalezione, gdzie operator oczekiwał w pobliżu" s/$ rx // r "i błąd składni w pobliżu tego samego – Johnathan1

+0

@JP. Och, to może być spowodowane twoją wersją perla .. której wersji używasz? – TLP