Programming

[Perl] 파일 이름 바꾸는 스크립트 (정규식 사용, 디렉토리 사용 가능)

Perl의 창시자인 Larry Wall이 Perl 책을 쓰던 시절에 그때부터 책에 수록되어 있었던 rename 스크립트가 있다. Perl 프로그래머라면 다들 알 지도 모르겠다.

요즘 어떤 리눅스 배포본에는 rename인지 rename.pl인지 하는 이름의 스크립트로 기본 설치가 되기도 하는 것 같다. (이건 확실하지 않다.)

정규식을 이용해서 편하게 이름 변환 규칙을 지정할 수 있다는 게 장점이다.

예를 들면, .doc 확장자를 가진 파일을 .txt로 변환한다고 하면, shell에서 for loop를 돌려서 매 파일마다 파일 이름 부분과 확장자 부분을 분리해서 확장자 부분만 바꿔치기하는 귀찮은 작업을 해줘야 한다. 하지만 rename.pl로 하면?

rename.pl 's/\.doc$/\.txt/' *.doc

이렇게 하면 된다. .doc로 끝나는 문자열이 있으면 그 부분을 .txt로 바꾸겠다는 의미이다.

이 스크립트을 아주 유용하게 잘 써왔는데, 파일이 상당히 많은 디렉토리에서 이 작업을 하면 몇 가지 단점이 나타난다. 일단 *.doc처럼 여러 파일을 지정할 경우, shell에 따라 argument 수가 너무 많아서 실행이 불가능한 경우가 있고, 또한 Perl인 점을 감안하더라도 속도가 너무 느리다. 그래서 디렉토리에 대해서 일괄 처리가 가능하도록 수정해봤다.

#!/usr/bin/env perl
#
# Usage: rename perlexpr [files or directory]
#
# updated by terzeron@gmail.com, 2009/10/07
# copied and updated by terzeron@indra.snu.ac.kr, 1997/09/20

use strict;
use English;

sub rename_file
{
my $pattern = shift;
my $file = shift;
my $dir = shift;

my $old_name = "$dir/$file";
$_ = $old_name;
eval $pattern;
my $new_name = $_;
#$old_name =~ s/([\?\&\*])/\\$1/og;
print "$old_name -> $new_name\n";
if ($old_name ne $new_name) {
if (not rename($old_name, $new_name)) {
print "can't rename $old_name to $new_name, $ERRNO\n";
return -1;
}
}
return 0;
}

sub main
{
# If no perlexpr argument exists, exit.
if (scalar @ARGV < 2) {
print STDERR
"Usage:\t$PROGRAM_NAME\t \n";
return -1;
}
my $pattern = shift @ARGV;

if (scalar @ARGV == 1 and -d $ARGV[0]) {
# directory
my $dir;
if (not opendir($dir, $ARGV[0])) {
print STDERR "can't open directory '$dir' for reading, $ERRNO\n";
return -1;
}
while ((my $file = readdir($dir))) {
if ($file eq "." or $file eq "..") {
next;
}
if (rename_file($pattern, $file, $ARGV[0]) < 0) {
return -1;
}
}
closedir($dir);
} else {
# file list
foreach my $file (@ARGV) {
if (rename_file($pattern, $file, "") < 0) {
return -1;
}
}
}
}

main();

이렇게 쓸 수 있다.

rename.pl 's/\.doc$/\.txt/' /home/terzeron/doc_dir

이렇게 쓰면 좀 더 빠르게 실행될 것이다.

rename.pl 's/\.doc$/\.txt/o' /home/terzeron/doc_dir

o modifier는 정규식을 compile하도록 지정하는 것이다. compile해놓고 여러 파일에 적용하면 빠르게 동작한다.

댓글 2개

답글 남기기