2011-12-09 24 views
7

ディレクトリを取得し、すべての電子メール(* .msg)ファイルに対して、最初に「RE」を削除します。私は次のコードがありますが、名前の変更は失敗します。Perlを使用してディレクトリ内のファイルの名前を変更する

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

エラー(!$)を印刷する場合は、あなたが間違っているかのアイデアを得るかもしれない... – pilcrow

+0

はそれを指摘いただきありがとうございます。エラーは 'No such file or directory'です。 $ oldのファイル名が正確であるので、私は驚いています。 – Johnathan1

+2

'rename'はクロスプラットフォームサポートを楽しんでいないことに注意してください。' File :: Copy'の 'move'関数は – Zaid

答えて

9

あなた./emailsディレクトリにこれらのファイルが含まれている場合:

1.msg 
2.msg 
3.msg 

、あなたの@files('.', '..', '1.msg', '2.msg', '3.msg')ようになりますが、あなたのrename'emails/1.msg''emails/2.msg'ような名前を望んでいる、などの名前を変更する前chdirすることができますので:

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

あなたはおそらくch戻り値もchdirにしてください。

またはディレクトリ名を自分で追加します。

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 

あなたはgrepを使用して、ディレクトリの読み取りおよびフィルタリングを組み合わせることが必要になる場合があります

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

かさえ、この:

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

優れています。これを説明していただきありがとうございます。 – Johnathan1

5

あなたはではなく、globのような行動を取っているようですのような動作。

readdirシステムコールは、ディレクトリ内のファイル名だけを返し、2つのエントリ...を含みます。これは、Perlのreaddir関数に伝わります。ちょうどmuの答えについて少し詳しく説明します。

代わりに、readdirを使用しても、配列内のすべての結果を収集することはあまりありません。

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

+1は 'glob'が存在することを思い出させます。 'glob'の欠点は、' 'emails/''接頭辞の存在により、名前の変更が少し複雑になることです。それはかなり軽微な問題であり、扱いが簡単ではありません。 –

2

前述のとおり、ご使用のスクリプトが期待するパスのためにスクリプトが失敗し、スクリプトの使用方法が同じではありません。

私はより透明な使用を提案します。ディレクトリをハードコーディングするのは良い考えではありません。ある日、私がオリジナルのファイルを変更するスクリプトを作ったときに、ハードコードされたパスと私の同僚が、コピーを変更するために借りる素敵なスクリプトだと思った。おっと!

用途:

perl script.pl "^RE " *.msg 

すなわち正規表現、例えばパスをスクリプトに関連して示され、その後ファイルグロブリスト、 *.msg,emails/*.msgまたはさらに/home/pat/emails/*.msg /home/foo/*.msgである。

絶対パスを使用すると、ユーザーはどのファイルに影響を与えるのか疑いがなくなり、スクリプトを再利用できるようになります。

コード:

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:WindowsのUnix-ificationを好きになる: – Zaid

+0

こんにちは、私は本当にこのアイデアが好きです。私は私の$ new = s/$ rx // rという行にエラーが表示されているようです。出力は「s/$ rx // r」の近くでオペレータが期待していた場所と同じ文法エラーで、同じ – Johnathan1

+0

@JPの近くに見つかったものです。ああ、それはあなたのperlのバージョンに起因するかもしれません..どのバージョンを使用していますか? – TLP

関連する問題