連続したファイル名に rename

あるディレクトリを指定して、そのディレクトリの中にあるファイルをすべて連番のファイル名に rename する処理を Perl で書いた。(なぜなら Mac 上でその作業を行う必要があったから。ツール探すより書いた方が早いと思ったんだもん。あ、MacPerl で実際に動かす場合はディレクトリの区切りは : じゃないとダメだと思う。)

基本的には以下の方法でイケる。

opendir( DIR, $dirname );
while ( $file = readdir( DIR ) ) {
  rename( $dirname.'/'.$file, $dirname.'/basename'.$serial );
  $serial++;
}

連番への rename 処理

でもこれでやっちゃうと、rename した瞬間にディレクトリエントリの順番が変わる場合に対処できない。

例えば MacOS でこれを動かすと、rename 後の file が最後のエントリに回り、抜けた分は繰り上がってしまう。つまり、すべてのエントリを順に rename しても、rename されないエントリが半分残り、逆に2回 rename されるエントリが半分できる。

したがって正解は

opendir( DIR, $dirname );
@files = readdir( DIR );
foreach $file ( @files ) {
  rename( $dirname.'/'.$file, $dirname.'/basename'.$serial );
  $serial++;
}

こうやってディレクトリエントリの変更が起きる前に全部配列に納めてしまう方法。

More